Two month ago I took part in a gamejam. Game jam is over, and it time to show what I made.For that gamejam i start rewriting my old prototype SaveShelter, game like wolfenstein 3d. It was cool prototype but, I was new to defold when start it, and it was made for gamejam, so it have some problems and strange code.
When I make that new prototype I try to keep code simple and good.
I still working on base things but first playable version where you can move, shoot and die, done=).
All sources on github. https://github.com/d954mas/2.5d-shooter
Features that already done.
1)Culling. Have go only for visible walls,objects.SaveShelter have problems with big levels. It was easy to get sprite or go limit. In new version only visible objects,walls will have go.
2)Cells color. Every cell can have a color. All objects in that cell and near wall will mix their color. SaveShelter have that feature but only for 16 colors for performance reason. Now any color can be used.In runtime game will create a lightmap texture and in shader mix colors.It work good for wall. But objects and enemies can be in two cells. For them use sprite.set_constant. It is bad because it break batching.But because theare are only visible go, it is not so bad.If some one have idea how to make it, better please tell me.
3)Fog. In shader. Can change distance and fog color.
4)Physics. Base colliders for walls and shoots.
5)Camera. Use rendercam. Rendercam is simple and awesome.
6)Pathfinding. Micropather,a c++ pathfinding lib.I have a lightweigth map copy in native, for pathfinding. Worked good and fast.
7)Mouse lock. For that I use defos.It can lock mouse but, locked mouse do not send input for defold . But there is a workaround. Hide mouse, and every frame move it position to center. Defold still do not get input, but you can save dx,dy and use it later.
if not IS_HTML then
if M.locked then
local x,y = defos.get_cursor_pos_view()
M.cursor_movement.x = x-RENDERCAM.window.x/2
M.cursor_movement.y = y-RENDERCAM.window.y/2
defos.set_cursor_pos_view(RENDERCAM.window.x/2, RENDERCAM.window.y/2) -- In game view coordinates
end
end
8)Pause modal. When you unlocked you mouse, game will be paused.I use my own scene manager. It was made about year ago. Few days ago I find that it not worked it release bundle . I use tostring(url) as a key in table.Do not do it.Use tostring(url.path).
9)Pickups. Pistol ammo and hp.
10)Simple enemy. Simple state machine.It follow player and hit in melee.
11)Weapons. I do not know the best way to do weapons. They can have different combinations of parameters, and OOP is not good for that. So I split weapon to weapon_base(logic) and weapon_prototype(config). Weapon_base use weapon_prototype and do some logic.
PISTOL = {attack_type = M.ATTACK_TYPES.RAYCASTING,ammo_type = M.AMMO_TYPES.PISTOL,target = M.TARGET.ENEMIES,
raycast_max_dist = 10, reload_time = 0, input_type = M.INPUT_TYPE.ON_PRESSED, player_weapon = true,
animations = {idle = hash("pistol_1")}, tag = "PISTOL";,
sounds = { shoot = SOUNDS.sounds.game.weapon_pistol_shoot, empty = SOUNDS.sounds.game.weapon_pistol_empty },
first_shot_delay = 0.1,shoot_time_delay = 0.4, damage = 25
}
12)Level editor. Defold editor is not good for that types of levels. So I used tiled. Level from tiled will saved in lua. Then I convert that lua file to my own format. I need my own format, because I need make some checks and precalculations. Also tiled output is contains useless and duplicated info. For example every level have tilesets description which is same for all of them.
13)Luacheck. Static code analysis. It help to keep code clean.
14)Tests. I newer made tests before. But it time to start.Use deftest for that. Now I have few basic tests.For exampe test that check that all levels can be loaded.
16)Transparent cells. For example vines.
17)ECS. Pattern for game logic.The main idea to use entities(bag for components), components(variables,for example position component) and systems(logic).System iterate entites that have some components, and do some work.So instead of having complex logic in one or few scripts. I have dozens of systems.
local ECS = require 'libs.ecs'
---@class MovementSystem:ECSSystem
local System = ECS.processingSystem()
System.filter = ECS.requireAll("position","velocity","speed")
---@param e Entity
function System:process(e, dt)
e.velocity = vmath.length(e.velocity) ~= 0 and vmath.normalize(e.velocity) or e.velocity
local movement = e.velocity * e.speed * dt
e.position.x = e.position.x + movement.x
e.position.y = e.position.y + movement.y
end
return System
18)Addaptive fov. Fov changed for differents screen sizes.
19)Resizer. Use defos and mnu to change game screen size.It is similar to simulate resolution from editor.
20)Weapon bobbing.