DEV Community

Cover image for Killing Those Blobs (Cosplore3D Pt:8)
Chig Beef
Chig Beef

Posted on

Killing Those Blobs (Cosplore3D Pt:8)

Intro

This is a new series following Cosplore3D, a raycaster game to learn 3D graphics. This project is part of 12 Months 12 Projects, a challenge I set myself.
We just did a bunch of work on the first level, Ankaran, but the gameplay is a bit dry, so we need to start actually implementing features that make the game fun.

Shooting Enemies

When we click, we should see if we shot an enemy.

func (w *Weapon) shoot(p *Player, enemies []*Enemy) {
    var e *Enemy
    var dx, dy, dis, angle float64

    w.curMag--

    for i := 0; i < len(enemies); i++ {
        e = enemies[i]

        dx = e.x - p.x
        dy = e.y - p.y
        dis = math.Sqrt(math.Pow(dx, 2) + math.Pow(dy, 2))
        angle = to_degrees(math.Acos(dx / dis))

        if math.Asin(dy/dis) < 0 {
            angle = -angle
        }

        // How much to the left or right of the player the enemy is
        angle -= p.angle
        angle = bound_angle(angle)

        if angle < w.bulletSize || angle > 360-w.bulletSize {
            e.health -= w.damage
            return
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

That looks pretty simple, right? All we're doing is looking through all enemies (although, once we've successfully shot an enemy we don't keep looking. We calculate the angle between the enemy and the player, and then if the angle is small enough then we hit the enemy.

Enemies Follow The Player

Now it was fun killing all the enemies, then grabbing the cosmium, but it really doesn't mean anything against static beings. So now we should make it so that the enemy tries to follow the player.

func (e *Enemy) follow_target() {
    var dx, dy, dis, angle float64

    dx = e.x - e.target.x
    dy = e.y - e.target.y
    dis = math.Sqrt(math.Pow(dx, 2) + math.Pow(dy, 2))
    angle = to_degrees(math.Acos(dx / dis))

    if math.Asin(dy/dis) < 0 {
        angle = -angle
    }

    // How much to the left or right of the player the enemy is
    angle = bound_angle(angle)

    e.x -= math.Cos(to_radians(angle)) * e.speed
    e.y -= math.Sin(to_radians(angle)) * e.speed

    e.angle = angle
}
Enter fullscreen mode Exit fullscreen mode

More Ammo

We have an Item struct, so we're going to use that for ammo as well. We need a way to give the player ammo whenever we collide with an ammo item. Here's my solution.

type Action func(*Game)

func giveAmmo(g *Game) {
    g.player.weapon.curMag += 10
    if g.player.weapon.curMag > g.player.weapon.mag {
        g.player.weapon.curMag = g.player.weapon.mag
    }
}
Enter fullscreen mode Exit fullscreen mode

We can create a type of function that takes a pointer to the Game as input. In this way, we can more easily give functionality to Items, but quite literally giving them functions.

Enemies Fight Back

Now we need to get the enemy to damage the player when it's too close.

func (e *Enemy) attack_target() {
    var dx, dy, dis float64

    dx = e.x - e.target.x
    dy = e.y - e.target.y
    dis = math.Sqrt(math.Pow(dx, 2) + math.Pow(dy, 2))

    if dis < e.attackRange {
        e.attackCooldown--
        if e.attackCooldown == 0 {
            e.target.health -= e.damage
            e.attackCooldown = e.roa
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Using attackCooldown, the enemy has to wait to attack again. And playing with this feature, I do lose health, and eventually my HUD shows no hearts.

Dying

What's the point of losing health if you can't die? So no we need to do something once we die. For now, I think we'll exit the game.

// Attempt to kill
if e.target.health <= 0 {
    os.Exit(0)
}
Enter fullscreen mode Exit fullscreen mode

I know that's quite a basic way to die, but I don't really know what I want to do when the player dies yet, whether I want it to instantly restart level, go back to some sort of menu, or anything like that, so for now this works and at least we have the logic.

Next

This gameplay is going quite well, but I feel too powerful being able to walk through walls, so we will have to fix that soon, most likely in the next post.

Top comments (0)