I'll start by being clear I'm not talking 3D models with lighting etc. I'm talking Wolfenstein flat 2D images that are placed on the screen in a way that gives you that first person vibe.
I have this top-down view of the world where the submarine, when looking through the periscope, has a very limited and narrow view of the world:
It can see the destroyer when the periscope faces it (the periscope can rotate) it but not the one's on either side. I want to build a 3D 'scene' that is very simple, very retro and very flat. Specifically, I'd like to show that one destroyer, as a flat 2D image that is positioned correctly (a little left of centre) and scaled down to the right size to give the perception of distance. Obviously, when the periscope "moves" left and right, the 2D flat image moves in the opposite direction.
I have a few things to work with. I know the x/y of the periscope. I know which way it is facing (degrees from north). I know the periscope has a 40 degree field of view (20 degrees left/right), I know the x/y of the destroyer(s), the viewable area (periscope viewport) is physically 350 pixels radius and I don't care about the destroyers facing/orientation (for now).
I've had a few failed attempts at the math and to project the image in the right position laterally with the right scale. This is complicated by the fact each destroyer has an x/y but the physical shape obviously is a rectangle that is more than a single point.
I'm not looking for a full-blown 3D immersive environment. My ambitions are minimal and was hoping someone has done math like this before, in terms of translating relative position from the viewer into correct placement in an X/Y sense and then scale to right size based on distance. I'm not even trying to get the y value right (on the horizon or below the horizon) at this stage.
This is the vision:
Even some journals on how Wolfenstein or Doom3D pulled this off would be great reading.
Translating a 2D world into a retro 3D first person perspective
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Translating a 2D world into a retro 3D first person perspective
Current project:
https://togfox.itch.io/backyard-gridiron-manager
American football manager/sim game - build and manage a roster and win season after season
https://togfox.itch.io/backyard-gridiron-manager
American football manager/sim game - build and manage a roster and win season after season
Re: Translating a 2D world into a retro 3D first person perspective
1. Create the same, but just with circles.
Each circle has x,y position on map, radius on map. By the given player position and periscope direction, it can be recalculated as x position on the screen and radius un the screen.
(Press WASD to move)
Each circle has x,y position on map, radius on map. By the given player position and periscope direction, it can be recalculated as x position on the screen and radius un the screen.
Code: Select all
function love.load()
Width, Height = love.graphics.getDimensions ()
MapCanvas = love.graphics.newCanvas (Width, Height, {dpiscale = 0.25})
Ships = {}
for i = 1, 4 do
local x = math.random (Width)
local y = math.random (Height)
local r = 20
local ship = {x=x, y=y, r=r}
table.insert (Ships, ship)
end
Player = {
-- x=Width/2, y=Height/4,
x=750, y=435,
r=20,
angle = 0,
angle = math.rad(183),
aov = math.rad(30), -- angle of view
lineLeft = {0,0,0,0}, lineRight = {0,0,0,0}, ships = {}}
--
ViewWidth = Width / 4 -- view width in pixels
ViewtoWidthFactor = ViewWidth / Player.aov -- factor pixels pro angle
end
function love.update(dt)
local w = love.keyboard.isScancodeDown ('w')
local a = love.keyboard.isScancodeDown ('a')
local s = love.keyboard.isScancodeDown ('s')
local d = love.keyboard.isScancodeDown ('d')
local speed = w and 1 or s and -1 or 0
local dangle = d and 1 or a and -1 or 0
Player.angle = (Player.angle + dt * dangle * 2)
Player.x = Player.x + dt * speed * 2*120 * math.cos (Player.angle)
Player.y = Player.y + dt * speed * 2*120 * math.sin (Player.angle)
love.window.setTitle ('sea battle '.. Player.x..' '.. Player.y..' '..math.deg(Player.angle))
-- update field of view
Player.lineLeft[1] = Player.x
Player.lineLeft[2] = Player.y
Player.lineLeft[3] = Player.x + 500*math.cos(Player.angle - Player.aov/2)
Player.lineLeft[4] = Player.y + 500*math.sin(Player.angle - Player.aov/2)
Player.lineRight[1] = Player.x
Player.lineRight[2] = Player.y
Player.lineRight[3] = Player.x + 500*math.cos(Player.angle + Player.aov/2)
Player.lineRight[4] = Player.y + 500*math.sin(Player.angle + Player.aov/2)
Player.ships = {}
for i, ship in ipairs (Ships) do
local vShip = {}
vShip.y = Height/2
local angle = (Player.angle - math.atan2 (ship.y-Player.y, ship.x-Player.x) + math.pi/2) % (2*math.pi) - math.pi/2
vShip.x = Width/2 - ViewtoWidthFactor * (angle)
vShip.r = 100* ship.r / math.sqrt((Player.x-ship.x)^2 + (Player.y-ship.y)^2)
if math.abs(Width/2 - vShip.x) < ViewWidth/2 then
table.insert (Player.ships, vShip)
end
end
end
function love.draw()
love.graphics.setCanvas (MapCanvas)
love.graphics.clear (0.1,0.1,0.3)
love.graphics.setColor (0.8,0.2,0.2)
for i, ship in ipairs (Ships) do
love.graphics.circle ('fill', ship.x, ship.y, ship.r)
end
love.graphics.setColor (0.2,0.8,0.2)
love.graphics.circle ('fill', Player.x, Player.y, Player.r)
love.graphics.setLineWidth (4)
love.graphics.line (Player.lineLeft)
love.graphics.line (Player.lineRight)
love.graphics.setCanvas ()
-- sky
love.graphics.setColor (0.6,0.7,0.8)
love.graphics.rectangle ('fill', 0,0, Width, Height/2)
-- sea
love.graphics.setColor (0.1,0.2,0.5)
love.graphics.rectangle ('fill', 0, Height/2, Width, Height/2)
-- ships in player's periscope
love.graphics.setColor (1,1,1)
for i, ship in ipairs (Player.ships) do
love.graphics.circle ('fill', ship.x, ship.y, ship.r)
end
-- periscope circle
love.graphics.setLineWidth (1)
love.graphics.circle ('line', Width/2, Height/2, ViewWidth/2)
-- map overlay
love.graphics.draw (MapCanvas, 0, 0, 0, 0.25, 0.25)
end
function love.keypressed(key, scancode, isrepeat)
if key == "escape" then
love.event.quit()
end
end
(Press WASD to move)
- Attachments
-
- sea-battle-01.love
- (1.17 KiB) Downloaded 19 times
Who is online
Users browsing this forum: slime and 52 guests