Intro
This is a series following Cosplore3D, a raycaster game to learn 3D graphics. This project is part of 12 Months 12 Projects, a challenge I set myself. In this post, we will be looking at how we can stop the player walking through walls by implementing collision.
Idea
There's no use checking whether the player is already colliding with a wall, because then we will be in the wall and we will be stuck. Instead, we will check whether we are about to collide with a wall. A short rod will be put out in front of us, and we will check whether this collides with a wall. If it does, then we can't move. The rod points right in front of us, where we are facing.
Equation For Collision Between Lines
We can check whether we are going to collide be seeing if the end of the rod is in a tile.
func (t *Tile) check_line_intersect(x, y float64) bool {
return x >= t.x && x <= t.x+t.w && y >= t.y && y <= t.y+t.y
}
Now when we move we can use this to decide whether we can move.
hit := false
tiles := g.levels[p.curLevel].get_solid_tiles()
for i := 0; i < len(tiles); i++ {
if tiles[i].check_line_intersect(rx, ry) {
hit = true
break
}
}
if !hit {
p.x = nx
p.y = ny
}
We can use the same logic on enemies and now they can't walk through walls either, an even playing field.
Enemies From Different Angles
I'm getting kind of sick of seeing the same image of an enemy from all angles, it doesn't really make sense, so I think we should start implementing that DOOM style sprite work.
var img *ebiten.Image
if vangle <= 45 || vangle >= 315 {
img = e.images[0]
} else if vangle > 45 && vangle <= 135 {
img = e.images[1]
} else if vangle > 135 && vangle <= 225 {
img = e.images[2]
} else {
img = e.images[3]
}
This turned out not to be too hard to implement, this is literally it, so I'm glad I got that out of the way.
Next
Being able to move through walls is weird, but so is being able to see through walls. In the next post we will fix the issue of seeing items and enemies through walls. We will also fix being able to shoot through walls.