Skip to content

Commit

Permalink
Level 1 is almost done, enemies must be able to damage
Browse files Browse the repository at this point in the history
  • Loading branch information
tatjam committed Jul 10, 2022
1 parent ca59b3c commit 354c879
Show file tree
Hide file tree
Showing 26 changed files with 229 additions and 49 deletions.
1 change: 1 addition & 0 deletions CREDITS.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Font used -> NicerNightie.ttf by unfilledflag
Binary file added res/barrier/door.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions res/barrier/door.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
sprite: res/barrier/door.png
fx_sprite: none
scale_origin: [16, 16]
animations:
- name: "default"
loop: false
frames:
- clip: [0, 0, 80, 100]
duration: 1.0
Binary file added res/barrier/door_lock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/barrier/exit.mp3
Binary file not shown.
Binary file added res/barrier/wood_break.mp3
Binary file not shown.
Binary file added res/barrier/wood_hurt.mp3
Binary file not shown.
2 changes: 2 additions & 0 deletions res/enemies/deadrockman.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
sprite: res/enemies/rockman.png
fx_sprite: none
scale_origin: [16, 16]
animations:
- name: "default"
loop: false
Expand Down
Binary file modified res/enemies/rockman.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified res/level1/map.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions res/level1/map.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@ points:

- name: rockman
color: [255, 100, 50]

- name: door
color: [0, 51, 255]
Binary file modified res/level1/map_ent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/tutorial/tut0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/tutorial/tut00.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/tutorial/tut000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/tutorial/tut1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/tutorial/tut2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/tutorial/tut3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 21 additions & 8 deletions src/game/entities/barrier.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,25 @@ const BARRIER_COLL = 42
type Barrier* = ref object
health: float
hurt_wav: WavHandle
break_wav: WavHandle
sprites*: seq[AnimatedSprite]
broken*: bool
phys_shape: Shape
phys_shape*: Shape
phys_space: Space
user_data*: UserData
# via physical impact at speed
enemies_damage: bool
objects_damage: bool
min_energy: float

proc hurt(this: Barrier, energy: float) =
echo "Was hurt"
proc hurt(this: var Barrier, energy: float) =
discard this.hurt_wav.play_sound()
this.health -= (energy - this.min_energy) / 300000.0
echo this.health

proc on_collide(this: Barrier, other: BodyKind, energy: float) =
proc on_collide*(this: var Barrier, other: BodyKind, energy: float) =
if (other == bkEnemy and this.enemies_damage) or
(other == bkObject and this.objects_damage):
if energy > 0:
echo "Collide with energy: " & $energy
if energy > this.min_energy:
this.hurt(energy)

Expand Down Expand Up @@ -74,7 +76,7 @@ proc create_barrier(sprite: string, area: Vec4f, size: int, space: Space, id: in

# The collider is a simple static segment
let hs = size.toFloat * 0.5
result.phys_shape = newSegmentShape(space.staticBody, v(area.x + hs, area.y + hs), v(area.z + hs, area.w + hs), 1)
result.phys_shape = newSegmentShape(space.staticBody, v(area.x + hs, area.y + hs), v(area.z + hs, area.w + hs), 8)
result.user_data = make_barrier_userdata(id)
result.phys_shape.userData = addr result.user_data
# We sign up for collision callbacks between everything and barriers
Expand All @@ -85,16 +87,27 @@ proc create_barrier(sprite: string, area: Vec4f, size: int, space: Space, id: in
handler.postSolveFunc = barrier_handler
handler.userData = barriers

result.phys_space = space

discard space.addShape(result.phys_shape)

proc create_wooden_barrier*(area: Vec4f, size: int, space: Space, id: int, barriers: ptr seq[Barrier]): Barrier =
result = create_barrier("res/level1/break_wood.yaml", area, size, space, id, barriers)
result.health = 10.0
result.min_energy = 1.0
result.min_energy = 1000000.0
result.enemies_damage = true
result.objects_damage = true
result.hurt_wav = load_sound("res/barrier/wood_hurt.mp3")
result.break_wav = load_sound("res/barrier/wood_break.mp3")

proc update*(this: var Barrier) =
for sprite in mitems(this.sprites):
sprite.animate(dt)
if this.health < 0.0:
discard this.break_wav.play_sound()
this.phys_space.removeShape(this.phys_shape)
this.broken = true


proc draw*(this: var Barrier) =
for sprite in this.sprites:
Expand Down
33 changes: 33 additions & 0 deletions src/game/entities/door.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
include ../../engine/base

import player
import glm
import math

import ../userdata
# Doors are positioned using their bottom left corner
type Door* = ref object
open_wav: WavHandle
sprite*: AnimatedSprite
sound: WavHandle
requires_key: bool


proc create_door*(pos: Vec2f): Door =
result = new(Door)
result.sprite = create_animated_sprite("res/barrier/door.yaml")
result.open_wav = load_sound("res/barrier/exit.mp3")
result.requires_key = false
result.sprite.position = vec2f(pos.x, pos.y - result.sprite.sprite.texture_height.toFloat)

proc update*(this: Door, player: Player): bool =
let diff = player.sprite.center_position - this.sprite.center_position
let dist = length(diff)

if dist < 50.0:

return true
return false

proc draw*(this: Door) =
renderer.draw(this.sprite)
13 changes: 11 additions & 2 deletions src/game/entities/enemy.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type
hurt_wav: WavHandle
sprite*: AnimatedSprite
phys_body*: Body
phys_shape: Shape
phys_shape*: Shape
user_data*: UserData
toss_timer: float

Expand All @@ -46,10 +46,14 @@ proc create_rockman*(pos: Vec2f, space: Space, id: int): Enemy =


proc die(this: var Enemy, objects: var seq[PhysicalObject], space: Space) =
let pos = this.phys_body.position
let vpos = vec2f(pos.x, pos.y)
space.removeShape(this.phys_shape)
space.removeBody(this.phys_body)
this.dead = true
discard
if this.kind == ekRockman:
# Spawn a dead rockman
objects.add(create_deadrockman(vpos, space, objects.len))

proc update*(this: var Enemy, player: Player, objects: var seq[PhysicalObject], space: Space) =
this.sprite.center_position = vec2f(this.phys_body.position.x, this.phys_body.position.y)
Expand All @@ -59,6 +63,7 @@ proc update*(this: var Enemy, player: Player, objects: var seq[PhysicalObject],
this.die(objects, space)

if this.toss_timer < 0.0:
this.phys_body.angle = 0.0
if this.kind == ekRockman:
# Simple moving towards player behaviour, with random retreats
if this.retreat:
Expand All @@ -82,6 +87,7 @@ proc update*(this: var Enemy, player: Player, objects: var seq[PhysicalObject],
else:
this.toss_timer -= dt

this.sprite.rotation = this.phys_body.angle

proc hurt*(this: var Enemy, point: Vect) =
this.health -= 1.0
Expand All @@ -93,6 +99,9 @@ proc hurt*(this: var Enemy, point: Vect) =
proc toss*(this: var Enemy) =
this.toss_timer = 2.0

proc is_tossable*(this: Enemy): bool =
return true

proc draw*(this: var Enemy) =
renderer.draw(this.sprite)

33 changes: 26 additions & 7 deletions src/game/entities/physical_object.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import ../userdata
type
ObjectKind = enum
okRock,
okMagmaRock
okMagmaRock,
okDeadRockman

PhysicalObject* = ref object
kind: ObjectKind
sprite*: AnimatedSprite
phys_body*: Body
phys_shape: Shape
phys_shape*: Shape
user_data: UserData

proc update*(this: var PhysicalObject) =
Expand All @@ -28,12 +29,12 @@ proc draw*(this: var PhysicalObject) =
proc create_rock*(pos: Vec2f, space: Space, id: int): PhysicalObject =
result = new(PhysicalObject)
result.sprite = create_animated_sprite("res/objects/rock.yaml")
let mass = 50.0
let mass = 40.0
let moment = momentForCircle(mass, 0.0, 58.0, vzero)

result.phys_body = space.addBody(newBody(mass, moment))
result.phys_shape = space.addShape(newCircleShape(result.phys_body, 58.0, vzero))
result.user_data = make_enemy_userdata(id)
result.user_data = make_object_userdata(id)
result.phys_shape.userData = addr result.user_data
result.phys_body.position = v(pos.x, pos.y)
result.phys_shape.friction = 0.1
Expand All @@ -43,14 +44,32 @@ proc create_rock*(pos: Vec2f, space: Space, id: int): PhysicalObject =
proc create_magmarock*(pos: Vec2f, space: Space, id: int): PhysicalObject =
result = new(PhysicalObject)
result.sprite = create_animated_sprite("res/objects/magmarock.yaml")
let mass = 60.0
let mass = 40.0
let moment = momentForCircle(mass, 0.0, 58.0, vzero)

result.phys_body = space.addBody(newBody(mass, moment))
result.phys_shape = space.addShape(newCircleShape(result.phys_body, 58.0, vzero))
result.user_data = make_enemy_userdata(id)
result.user_data = make_object_userdata(id)
result.phys_shape.userData = addr result.user_data
result.phys_body.position = v(pos.x, pos.y)
result.phys_shape.friction = 0.1

result.kind = okMagmaRock
result.kind = okMagmaRock

proc create_deadrockman*(pos: Vec2f, space: Space, id: int): PhysicalObject =
result = new(PhysicalObject)
result.sprite = create_animated_sprite("res/enemies/deadrockman.yaml")
let mass = 12.0
let moment = momentForBox(mass, 12.0, 12.0)

result.phys_body = space.addBody(newBody(mass, moment))
result.phys_shape = space.addShape(newBoxShape(result.phys_body, 12.0, 12.0, 0.0))
result.user_data = make_object_userdata(id)
result.phys_shape.userData = addr result.user_data
result.phys_body.position = v(pos.x, pos.y)
result.phys_shape.friction = 0.7

result.kind = okDeadRockman

proc is_tossable*(this: PhysicalObject): bool =
return this.kind == okDeadRockman
47 changes: 32 additions & 15 deletions src/game/entities/player.nim
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
include ../../engine/base
import nimgl/glfw
import ../userdata
import random


type Player* = ref object
sprite*: AnimatedSprite
lantern*: Sprite

phys_body: Body
phys_shape: Shape
phys_body*: Body
phys_shape*: Shape
phys_space: Space

last_jump: bool
Expand Down Expand Up @@ -89,8 +90,9 @@ proc query_hit(sh: Shape, p: Vect, n: Vect, a: Float, data: pointer) {.cdecl.} =
if udata.kind == bkEnemy:
let enemy_idx = udata.point
var datac = cast[ptr ToHitData](data)
datac[].hit = true
hurt(datac[].enemies[enemy_idx], p)
if not datac[].enemies[enemy_idx].dead:
datac[].hit = true
hurt(datac[].enemies[enemy_idx], p)


proc hit(this: Player, enemies: seq[Enemy]): bool =
Expand All @@ -114,28 +116,39 @@ type ToTossData = object
enemies: seq[Enemy]
objects: seq[PhysicalObject]
force: Vect
tossed: seq[pointer]

proc query_toss(sh: Shape, p: Vect, n: Vect, a: Float, data: pointer) {.cdecl.} =
# There's this weird 38 user data that we must ignore
var body: Body = nil
var datac = cast[ptr ToTossData](data)
if cast[int](sh.userData) > 100000:
let udata = cast[ptr UserData](sh.userData)[]
if datac[].tossed.contains(cast[pointer](udata)):
return
if udata.kind == bkEnemy:
let enemy_idx = udata.point
body = datac[].enemies[enemy_idx].phys_body
datac[].enemies[enemy_idx].toss()
let enemy = datac[].enemies[enemy_idx]
if enemy.is_tossable() and not enemy.dead:
body = enemy.phys_body
datac[].enemies[enemy_idx].toss()
datac[].tossed.add(cast[pointer](udata))
elif udata.kind == bkObject:
let object_idx = udata.point
body = datac[].objects[object_idx].phys_body
if datac[].objects[object_idx].is_tossable():
body = datac[].objects[object_idx].phys_body
datac[].tossed.add(cast[pointer](udata))

if body != nil:
let fp = body.position
body.applyImpulseAtWorldPoint(fp, datac[].force)
var cm = body.centerOfGravity
var fp = body.localToWorld(cm)
fp = v(fp.x + rand(10.0), fp.y + rand(10.0))
body.applyImpulseAtWorldPoint(datac[].force, fp)

proc toss(this: Player, enemies: seq[Enemy], objects: seq[PhysicalObject]) =
let rays = this.phys_body.position + v(0.0, 0.0)
var raye = this.phys_body.position + v(34.0, 23.0)
var raye = this.phys_body.position + v(48.0, 23.0)
var raye2 = this.phys_body.position + v(48.0, 0.0)
if this.sprite.scale.x < 0.0:
raye = this.phys_body.position + v(-34.0, 23.0)

Expand All @@ -161,16 +174,20 @@ proc toss(this: Player, enemies: seq[Enemy], objects: seq[PhysicalObject]) =
return

# Direction
var ver = 0.5 * sin(PI * toss_prog)
var ver = 1.0 * (sin(PI * toss_prog) + 0.2)
if this.sprite.scale.x < 0.0:
query_data.force = v(-1.0, -ver)
else:
query_data.force = v(1.0, -ver)
let len = query_data.force.vlength
query_data.force = v(query_data.force.x / len, query_data.force.y / len)

var force = 300.0 * (cos(PI * 0.5 * toss_prog - PI * 0.5) + 0.3)
var force = 7000.0 * (cos(PI * 0.5 * toss_prog - PI * 0.5) + 0.3)
query_data.force = v(query_data.force.x * force, query_data.force.y * force)

segmentQuery(this.phys_space, rays, raye, Float(4.0), filter, query_toss, addr query_data)
# We do two querys
segmentQuery(this.phys_space, rays, raye, Float(14.0), filter, query_toss, addr query_data)
segmentQuery(this.phys_space, rays, raye2, Float(14.0), filter, query_toss, addr query_data)

proc update*(this: var Player, enemies: seq[Enemy], objects: seq[PhysicalObject]) =
# Ground check
Expand Down Expand Up @@ -233,11 +250,11 @@ proc update*(this: var Player, enemies: seq[Enemy], objects: seq[PhysicalObject]
else:
var lateral = false
if glfw_window.getKey(GLFWKey.A) == GLFW_PRESS:
this.phys_body.position = this.phys_body.position + v(-dt * 100.0, 0.0)
this.phys_body.position = this.phys_body.position + v(-dt * 120.0, 0.0)
this.sprite.scale = vec2f(-1.0, 1.0)
lateral = true
if glfw_window.getKey(GLFWKey.D) == GLFW_PRESS:
this.phys_body.position = this.phys_body.position + v(dt * 100.0, 0.0)
this.phys_body.position = this.phys_body.position + v(dt * 120.0, 0.0)
this.sprite.scale = vec2f(1.0, 1.0)
lateral = true
if glfw_window.getKey(GLFWKey.V) == GLFW_PRESS:
Expand Down
Loading

0 comments on commit 354c879

Please sign in to comment.