Skip to content

Instantly share code, notes, and snippets.

@st235
Last active February 6, 2025 18:52
Show Gist options
  • Save st235/e3d5610924d5cbaa9e487616f68880e7 to your computer and use it in GitHub Desktop.
Save st235/e3d5610924d5cbaa9e487616f68880e7 to your computer and use it in GitHub Desktop.
Dinosaurs Game
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 712
RUNAWAY_HEIGHT = 40
CHARACTER_WIDTH = 24
CHARACTER_HEIGHT = 24
CHARACTER_SCALE = 4
CHARACTER_ANIMATION_CHANGE = 0.065
CHARACTER_VERTICAL_SPEED = -500
CHARACTER_VERTICAL_ACCELERATION = 800
CHARACTER_MAX_Y = (WINDOW_HEIGHT - CHARACTER_HEIGHT * CHARACTER_SCALE - RUNAWAY_HEIGHT) + 4 * CHARACTER_SCALE
CACTUS_WIDTH = 32
CACTUS_HEIGHT = 32
CACTUS_HORIZONTAL_SPEED = -60
CACTUS_HORIZONTAL_ACCELERATION = -10
CACTUS_SPAWN_TIME = 5
CACTUS_SCALE = 2
function math.clamp(low, n, high)
return math.min(math.max(n, low), high)
end
-- s1 f1
-- s2 f2
local function intersection(s1, f1, s2, f2)
if (math.max(s1, s2) <= math.min(f1, f2)) then
return true
else
return false
end
end
local function hitsCactus(cx1, cx2, cy1, cy2)
local op = 8 * CHARACTER_SCALE
local ox1 = (WINDOW_WIDTH - CHARACTER_WIDTH * CHARACTER_SCALE) // 2 + op
local ox2 = (WINDOW_WIDTH + CHARACTER_WIDTH * CHARACTER_SCALE) // 2 - op
local oy1 = character_origin_y + op
local oy2 = character_origin_y + CHARACTER_HEIGHT * CHARACTER_SCALE - op
return intersection(ox1, ox2, cx1 + 4 * CACTUS_SCALE, cx2) and intersection(oy1, oy2, cy1, cy2)
end
function engine.start()
engine.window.setTitle("Run dino 🦖")
engine.window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT)
-- See /gameplay/resources
font = engine.graphics.newFont("PixeloidSans.ttf", 72)
runaway = engine.graphics.newRect(WINDOW_WIDTH, RUNAWAY_HEIGHT, {210, 210, 207})
plants_atlas = engine.graphics.loadTexture("pixel_cactus.png")
cactus_quad = engine.graphics.newQuad(32, 0, CACTUS_WIDTH, CACTUS_HEIGHT)
star = engine.graphics.loadTexture("star.png")
particles_system = engine.graphics.newParticlesSystem(50)
particles_system:setTexture(star)
particles_system:setEmissionRate(10)
particles_system:setCenterPosition(WINDOW_WIDTH // 2, -40)
particles_system:setParticlesLifetime(0.5, 5.5)
particles_system:setAcceleration(-30, -50, 70, 120)
particles_system:setAngularMomentum(-50, 50)
particles_system:setScale(1, 1.8)
particles_system:setAlphaDecay(1.0, 0.0)
particles_system:setRectangularEmitter(WINDOW_WIDTH, 40)
character_atlas = engine.graphics.loadTexture("Dino.png")
character_running_animation = {
engine.graphics.newQuad(24*5, 0, CHARACTER_WIDTH, CHARACTER_HEIGHT),
engine.graphics.newQuad(24*6, 0, CHARACTER_WIDTH, CHARACTER_HEIGHT),
engine.graphics.newQuad(24*7, 0, CHARACTER_WIDTH, CHARACTER_HEIGHT),
engine.graphics.newQuad(24*8, 0, CHARACTER_WIDTH, CHARACTER_HEIGHT),
}
character_animation_timer = 0
character_animation_frame = 0
character_origin_y = CHARACTER_MAX_Y
character_vspeed = 0
character_state = "running"
score = 0
score_text = engine.graphics.newText(font, tostring(score), { 27, 18, 18 })
music = engine.audio.newMusic("music.mp3")
music:setRepeatCount(-1)
jump_up_effect = engine.audio.newEffect("jump.mp3")
coin_effect = engine.audio.newEffect("coin.mp3")
trombone_effect = engine.audio.newEffect("trombone.mp3")
enemies_spawner = CACTUS_SPAWN_TIME
enemies_positions = {}
game_state = "finish"
end
local function onInput()
if (game_state == "finish") then
character_animation_timer = 0
character_animation_frame = 0
character_origin_y = CHARACTER_MAX_Y
character_vspeed = 0
character_state = "running"
score = 0
score_text = engine.graphics.newText(font, tostring(score), { 27, 18, 18 })
enemies_spawner = CACTUS_SPAWN_TIME
enemies_positions = {}
game_state = "running"
CACTUS_HORIZONTAL_SPEED = -60
music:play()
return
end
if (character_state == "running") then
character_state = "jumping"
character_vspeed = CHARACTER_VERTICAL_SPEED
jump_up_effect:play()
return
end
end
function engine.onMouseDown(e)
if (e:button() == "left") then
onInput()
end
end
function engine.onKeyDown(e)
if (e:keycode() == "space") then
onInput()
end
end
function engine.update(dt)
if game_state ~= "running" then
return
end
particles_system:update(dt)
if (character_state == "jumping") then
character_vspeed = character_vspeed + CHARACTER_VERTICAL_ACCELERATION * dt
character_origin_y = math.clamp(character_origin_y + character_vspeed * dt, 0, CHARACTER_MAX_Y)
if (character_origin_y >= CHARACTER_MAX_Y) then
character_vspeed = 0
character_state = "running"
end
end
character_animation_timer = character_animation_timer + dt
if (character_animation_timer > CHARACTER_ANIMATION_CHANGE) then
character_animation_frame = (character_animation_frame + 1) % #character_running_animation
character_animation_timer = 0
end
for i, _ in pairs(enemies_positions) do
enemies_positions[i] = enemies_positions[i] + CACTUS_HORIZONTAL_SPEED * dt
local cx1 = enemies_positions[i]
local cx2 = cx1 + CACTUS_WIDTH * CACTUS_SCALE
local cy1 = WINDOW_HEIGHT - CACTUS_HEIGHT * CACTUS_SCALE - RUNAWAY_HEIGHT
local cy2 = cy1 + CACTUS_HEIGHT * CACTUS_SCALE
if hitsCactus(cx1, cx2, cy1, cy2) then
game_state = "finish"
trombone_effect:play();
music:stop();
end
end
for i, _ in pairs(enemies_positions) do
if (enemies_positions[i] < -CACTUS_WIDTH * CACTUS_SCALE) then
table.remove(enemies_positions, i)
score = score + 1
score_text = engine.graphics.newText(font, tostring(score), { 27, 18, 18 })
coin_effect:play()
end
end
enemies_spawner = enemies_spawner + dt
if (enemies_spawner > CACTUS_SPAWN_TIME) then
enemies_spawner = 0
table.insert(enemies_positions, WINDOW_WIDTH)
end
CACTUS_HORIZONTAL_SPEED = CACTUS_HORIZONTAL_SPEED + CACTUS_HORIZONTAL_ACCELERATION * dt
end
function engine.draw()
engine.graphics.clear(175, 225, 175)
particles_system:draw()
engine.graphics.draw(runaway,
(WINDOW_WIDTH - runaway:width()) // 2,
(WINDOW_HEIGHT - runaway:height()))
engine.graphics.draw(score_text,
(WINDOW_WIDTH - score_text:width()) // 2,
(WINDOW_HEIGHT - score_text:height()) // 2)
for _, enemy in pairs(enemies_positions) do
engine.graphics.draw(plants_atlas,
cactus_quad,
math.ceil(enemy),
math.ceil(WINDOW_HEIGHT - CACTUS_HEIGHT * CACTUS_SCALE - RUNAWAY_HEIGHT),
0, CACTUS_SCALE, CACTUS_SCALE)
end
engine.graphics.draw(character_atlas,
character_running_animation[character_animation_frame + 1],
(WINDOW_WIDTH - CHARACTER_WIDTH * CHARACTER_SCALE) // 2,
math.ceil(character_origin_y),
0, CHARACTER_SCALE, CHARACTER_SCALE)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment