Fat Old Yeti

Fat Old Yeti

Being a blog of thoughts and tutorials from a hobby game developer.

09 Feb 2022

Roguelike Tutorial 18

Roguelike in Go - Part 18 (Variety of Bad Guys)

All of the source code for this tutorial can be found here.

So, at this point, we have skeletons to find and fight. I think it’s time to add another monster to the mix. I whipped up an orc sprite to add a bit of variety. The sprite is in the assets folder, so make sure to grab it.

All the code for this will go into the world.go file. Open it up and look for:

	playerImg, _, err := ebitenutil.NewImageFromFile("assets/player.png")
	if err != nil {
		log.Fatal(err)
	}
	skellyImg, _, err := ebitenutil.NewImageFromFile("assets/skelly.png")
	if err != nil {
		log.Fatal(err)
	}

Directly underneath this, lets get the orc image:

	orcImg, _, err := ebitenutil.NewImageFromFile("assets/orc.png")
	if err != nil {
		log.Fatal(err)
	}

Now all we have to do is change the loop where the monster entities are being created. I’m just essentially flipping a coin to decide whether it should be an orc or a skeleton. I’ll just put the whole changed code here for the loop, because at this point, it should be easily readable:

	//Add a Monster in each room except the player's room
	for _, room := range startingLevel.Rooms {
		if room.X1 != startingRoom.X1 {
			mX, mY := room.Center()

			//Flip a coin to see what to add...
			mobSpawn := GetDiceRoll(2)

			if mobSpawn == 1 {
				manager.NewEntity().
					AddComponent(monster, &Monster{}).
					AddComponent(renderable, &Renderable{
						Image: orcImg,
					}).
					AddComponent(position, &Position{
						X: mX,
						Y: mY,
					}).
					AddComponent(health, &Health{
						MaxHealth:     30,
						CurrentHealth: 30,
					}).
					AddComponent(meleeWeapon, &MeleeWeapon{
						Name:          "Machete",
						MinimumDamage: 4,
						MaximumDamage: 8,
						ToHitBonus:    1,
					}).
					AddComponent(armor, &Armor{
						Name:       "Leather",
						Defense:    5,
						ArmorClass: 6,
					}).
					AddComponent(name, &Name{Label: "Orc"}).
					AddComponent(userMessage, &UserMessage{
						AttackMessage:    "",
						DeadMessage:      "",
						GameStateMessage: "",
					})
			} else {
				manager.NewEntity().
					AddComponent(monster, &Monster{}).
					AddComponent(renderable, &Renderable{
						Image: skellyImg,
					}).
					AddComponent(position, &Position{
						X: mX,
						Y: mY,
					}).
					AddComponent(health, &Health{
						MaxHealth:     10,
						CurrentHealth: 10,
					}).
					AddComponent(meleeWeapon, &MeleeWeapon{
						Name:          "Short Sword",
						MinimumDamage: 2,
						MaximumDamage: 6,
						ToHitBonus:    0,
					}).
					AddComponent(armor, &Armor{
						Name:       "Bone",
						Defense:    3,
						ArmorClass: 4,
					}).
					AddComponent(name, &Name{Label: "Skeleton"}).
					AddComponent(userMessage, &UserMessage{
						AttackMessage:    "",
						DeadMessage:      "",
						GameStateMessage: "",
					})
			}

		}

Now if you run the game, you will have both orcs and skeletons.

Of course, you probably would agree with me that world is getting a bit messy. If I were making this into a real game, I’d refactor this out into smaller files per entity type. I’d also load all entities from data files, allowing me a simple spot to change values. Yeah, and I’d probably not spawn just one entity in each room at the center. These are all things to consider when adding monsters to your rooms.

If you have any questions on this tutorial, feel free to hit me up at fatoldyeti@gmail.com or @idiotcoder on the gophers slack. In addition, I’m on the Ebiten Discord as Idiotcoder. Also, there is my discord linked above.