# Need help with enemy spawn coords

High all it’s me again the guy who disappeared. Anyway I need some help with a game. But before I go on yes I’m finishing this one and will try my hardest to post it. Now the problem recently I’ve been making a undertake maker and by that you just edit and make your own fight menu sorta thing but bad guy spawning is trick why? Because I have to make it every time you press a button a bad guy appears where the cursor is but I want to do this without having ten int’s saying enemy_x,enemy_x2 ect, so how simply would I do just this without having a thousands of int’s.

Also here’s a pic

for the game

Here’s a very hastily knocked together example of a `Point` class and a `PointList` class:

``````struct Point
{
uint8_t X;
uint8_t Y;

Point(void) : X(), Y() {}
Point(uint8_t x, uint8_t y) : X(x), Y(y) {}
};

template<int N>
struct PointList
{
private:
Point array[N];
uint8_t next;

// Returns the number of Points currently in the list
uint8_t Count(void) const { return next; }

// Returns the maximum number of Points the list can hold
uint8_t Capacity(void) const { return N; }

// Returns true if the list is full
bool IsFull(void) const { return Count() == Capacity(); }

// Returns true if the list is empty
bool IsEmpty(void) const { return Count() == 0; }

// Clears the list (by cheating)
void Clear(void) { next = 0; }

// Returns true if the Point was added
// Returns false if the list is already full
{
if(IsFull())
return false;

array[next] = point; // put the point in the array
++next; // increment the next index
return true;
}

// Returns true if the Point was removed
// Returns false if the index was invalid
bool RemoveAt(uint8_t index)
{
if(index >= next)
return false;

--next; // decrement next index
for(int i = index; i < next; ++i) // shuffle everything down
array[i] = array[i + 1];
return true;
}

// These are for indexing the list
// Be careful, these don't check if the index is valid
Point & operator[](uint8_t index) { return array[index]; }
const Point & operator[](uint8_t index) const { return array[index]; }
};
``````

You can use it like so:

``````PointList<10> list; // list can contain up to 10 points

Point cursor; // you can use a Point to store the player's cursor position

if(list.IsFull())
{
// if the list is full, stop letting the player add new spawn locations
}

Point p = list[4]; // get the 5th item in the list
``````

Bear in mind that having a list like this is only half the battle, you still have to write the user interface and hook together all the other junk but this should be a good start.

If you don’t understand what some of the stuff is, don’t worry about it too much, you only really need to understand how to use the list, not necissarily how it works.

If you have any questions about how the class works, feel free to ask, though I made sure to comment everything so it should be pretty straightforward.

What ints would be used in this?

Not sure I understood

@Pharap’s structure for the point uses uint8_t which is an unsigned, 8 bit integer and is identical to a byte.

1 Like

@filmote’s right, the `Point` structure uses `uint8_t` which is a synonym for `byte`, which itself is a synonym for `unsigned char`, which on the Arduboy is an unsigned 8-bit number ranging from 0 to 255.

If you really need more than that (which you might if your world is larger than the screen) then just change the uses of `uint8_t` in point with something more appropriate, like `uint16_t` or `int16_t`. (Which are the same as `unsigned int` and `signed int` on the Arduboy).

e.g.

``````struct Point
{
uint16_t X;
uint16_t Y;

Point(void) : X(), Y() {}
Point(uint16_t x, uint16_t y) : X(x), Y(y) {}
};
``````

The list won’t need to be changed unless you need more than 255 items.

So how would you use this to make it so if the arduboy presses a button is prints an enemy on the x and y cursor?

I don’t get what you mean.

I’m trying to make so when the arduboy presses the a button a baddy bit map is added and when I press play he chases the player. Also would it be aesier if I sent you the code?

Ok, that’s several different problems rather than just one.

• Deciding how to represent an enemy (a pointer to sprite data, a position, possibly other things like health)
• Maintaining a list of enemies (or just a list of the places you’re going to put them).
• Adding to the list in response to button presses.
• Making the enemy chase the player.

Ideally, or at least say how much you have already solved.

The list class I posted solves the problem of maintaining and adding to a list of positions.
With a bit of modification it can be made into a list of enemies but I can’t do that myself without knowing what the enemy class is called or how the enemies are structured.

I’ve got to placing a baddy in a body-x and body-y coordinate thas it. I will try send the code but how on earth does one do so? Git hub keeps messing it up!

Just the one?

Messing up how?
Are you using the website, a command line tool or a github client?

I’m using the website and it won’t let me paste so I crt+v and it doesn’t come across properly and it miss runs. Although if I’m desperate I could post it as text here.

I’m not sure why it won’t let you paste your code, it usually works fine for me.

You might just have to paste here for simplicity if you’re having issues with github.

You could also try using Github Desktop. I don’t use it personally but I know people who do.

If you could at least post your enemy class I’d at least be able to show you how to maintain a list of enemies.

1 Like
``````//main

#include <Arduboy2.h>
#include "Bitmaps.h"
Arduboy2 arduboy;

int x = 0;
int y = 0;

int sizex = 0;
int sizey = 0;

int heart_type = 0;

int velocity = 5;
int jump = 0;

int count = 0;

int rnd_x = 0;
int rnd_y = 0;

int enemyx = 0;
int enemyy = 0;

int gamestate = 0;

int screen = 0;

int dir = 0;
int dir2 = 0;
int enemycount = 0;
void setup()
{
arduboy.begin();

}

void loop()
{
switch ( gamestate )
{
case 0:
arduboy.clear();
arduboy.drawBitmap(0,0,undertale,16,16,WHITE);
arduboy.setCursor(0,20);
arduboy.setTextSize(2);
arduboy.print("Undertale\nMaker");
count++;
if(count == 80)
{
gamestate = 1;
count = 0;
}
arduboy.display();

break;
case 1:
arduboy.clear();
arduboy.pollButtons();
if(arduboy.justPressed(A_BUTTON))
{
gamestate =2;
}
if(arduboy.justPressed(UP_BUTTON))
{
gamestate = 3;
}
if(arduboy.justPressed(DOWN_BUTTON))
{
gamestate = 4;
}
if(arduboy.justPressed(B_BUTTON))
{
gamestate = 5;
}
arduboy.setTextSize(0);
arduboy.print("A_Heart_Options\n\nB_Enemy_Options\n\nDown_Run_Game\n\nUp_Areana");
if(heart_type == 0)
{
arduboy.setCursor(100,40);
arduboy.print("Red");
}
if(heart_type == 1)
{
arduboy.setCursor(90,40);
arduboy.print("Purple");
}
if(heart_type == 2)
{
arduboy.setCursor(90,40);
arduboy.print("Yellow");
}
if(heart_type == 3)
{
arduboy.setCursor(100,40);
arduboy.print("Blue");
}

arduboy.display();
break;
case 2:
arduboy.clear();
arduboy.pollButtons();
if(heart_type == 0)
{
arduboy.print("Red");
heart_type = 0;
}
if(heart_type == 1)
{
arduboy.print("Purple");
heart_type = 1;
}
if(heart_type == 2)
{
arduboy.print("Yellow");
heart_type = 2;
}
if(heart_type == 3)
{
arduboy.print("Blue");
heart_type = 3;

}
if(arduboy.justPressed(UP_BUTTON))
{
heart_type = heart_type -1;
}
if(arduboy.justPressed(DOWN_BUTTON))
{
heart_type = heart_type +1;
}
if(arduboy.justPressed(A_BUTTON))
{
gamestate = 1;
}
if(arduboy.justPressed(A_BUTTON) and arduboy.justPressed(B_BUTTON))
{
gamestate = 4;
}
arduboy.drawBitmap(100,0,undertale,16,16,WHITE);
if(heart_type<0)heart_type = 0;
if(heart_type>3)heart_type = 3;
arduboy.display();
break;
case 3:
arduboy.clear();
arduboy.pollButtons();
if(arduboy.justPressed(LEFT_BUTTON))
{
screen--;
}
if(arduboy.justPressed(RIGHT_BUTTON))
{
screen++;
}
if(screen == 1)
{
arduboy.fillRect(0,0,50,25);
arduboy.fillRect(1,1,48,23,BLACK);
}
if(screen == 2)
{
arduboy.fillRect(0,0,25,50);
arduboy.fillRect(1,1,23,48,BLACK);
}
if(screen == 3)
{
arduboy.fillRect(0,0,50,50);
arduboy.fillRect(1,1,48,48,BLACK);
}
if(screen == 4)
{
arduboy.fillRect(0,0,60,30);
arduboy.fillRect(1,1,58,28,BLACK);
}
if(screen == 5)
{
arduboy.fillRect(0,0,30,60);
arduboy.fillRect(1,1,28,58,BLACK);
}
if(screen == 6)
{
arduboy.fillRect(0,0,60,60);
arduboy.fillRect(1,1,58,58,BLACK);
}

if(arduboy.justPressed(A_BUTTON))
{
gamestate = 1;
}
if(screen < 1)screen = 1;
if(screen > 6)screen = 6;
arduboy.display();
break;
case 4:
arduboy.pollButtons();
arduboy.clear();
if(screen == 1)
{
arduboy.fillRect(0,0,50,25);
arduboy.fillRect(1,1,48,23,BLACK);
}
if(screen == 2)
{
arduboy.fillRect(0,0,25,50);
arduboy.fillRect(1,1,23,48,BLACK);
}
if(screen == 3)
{
arduboy.fillRect(0,0,50,50);
arduboy.fillRect(1,1,48,48,BLACK);
}
if(screen == 4)
{
arduboy.fillRect(0,0,60,30);
arduboy.fillRect(1,1,58,28,BLACK);
}
if(screen == 5)
{
arduboy.fillRect(0,0,30,60);
arduboy.fillRect(1,1,28,58,BLACK);
}
if(screen == 6)
{
arduboy.fillRect(0,0,60,60);
arduboy.fillRect(1,1,58,58,BLACK);
}
if(heart_type == 0)
{
if(screen == 1)
{
if(x > 40)x = 40;
if(x < 0)x = 0;
if(y > 16)y = 16;
if(y < 0)y = 0;
}
if(screen == 2)
{
if(x > 15)x =15;
if(x < 0)x = 0;
if(y > 41)y = 41;
if(y < 0)y = 0;
}if(screen == 3)
{
if(x > 40)x = 40;
if(x < 0)x = 0;
if(y > 41)y = 41;
if(y < 0)y = 0;
}
if(screen == 4)
{
if(x > 50)x = 50;
if(x < 0)x = 0;
if(y > 21)y = 21;
if(y < 0)y = 0;
}
if(screen == 5)
{
if(x > 20)x = 20;
if(x < 0)x= 0;
if(y > 51)y = 51;
if(y < 0)y = 0;
}
if(screen == 6)
{
if(x > 50)x = 50;
if(x < 0)x = 0;
if(y > 51)y = 51;
if(y < 0)y = 0;
}
arduboy.drawBitmap(x+1,y+1,heart,8,8,WHITE);
if(arduboy.pressed(UP_BUTTON))
{
y--;
}
if(arduboy.pressed(DOWN_BUTTON))
{
y++;
}
if(arduboy.pressed(LEFT_BUTTON))
{
x--;
}
if(arduboy.pressed(RIGHT_BUTTON))
{
x++;
}

if(arduboy.justPressed(B_BUTTON))
{
gamestate = 1;
enemyx = 0;
enemyy = 0;
}
}

if(heart_type == 1)
{
if(screen == 1)
{
if(x > 41)x = 41;
if(x < 1)x = 1;
if(y > 17)y = 17;
if(y < 1)y = 1;
}
if(screen == 2)
{
if(x > 16)x =16;
if(x < 1)x = 1;
if(y > 42)y = 42;
if(y < 1)y = 1;
}if(screen == 3)
{
if(x > 41)x = 41;
if(x < 1)x = 1;
if(y > 42)y = 42;
if(y < 1)y = 1;
}
if(screen == 4)
{
if(x > 51)x = 51;
if(x < 1)x = 1;
if(y > 22)y = 22;
if(y < 1)y = 1;
}
if(screen == 5)
{
if(x > 21)x = 21;
if(x < 1)x= 1;
if(y > 52)y = 52;
if(y < 1)y = 1;
}
if(screen == 6)
{
if(x > 51)x = 51;
if(x < 1)x = 1;
if(y > 52)y = 52;
if(y < 1)y = 1;
}
if(arduboy.justPressed(DOWN_BUTTON))
{
y = y + 10;
}
if(arduboy.justPressed(UP_BUTTON))
{
y = y - 10;
}
if(arduboy.pressed(LEFT_BUTTON))
{
x--;
}
if(arduboy.pressed(RIGHT_BUTTON))
{
x++;
}
if(arduboy.justPressed(B_BUTTON))
{
gamestate = 1;
}
arduboy.drawBitmap(x,y,heart,8,8,WHITE);
}

if(heart_type == 2)
{  if(screen == 1)
{
if(x > 41)x = 41;
if(x < 1)x = 1;
if(y > 17)y = 17;
if(y < 1)y = 1;
}
if(screen == 2)
{
if(x > 16)x =16;
if(x < 1)x = 1;
if(y > 42)y = 42;
if(y < 1)y = 1;
}if(screen == 3)
{
if(x > 41)x = 41;
if(x < 1)x = 1;
if(y > 42)y = 42;
if(y < 1)y = 1;
}
if(screen == 4)
{
if(x > 51)x = 51;
if(x < 1)x = 1;
if(y > 22)y = 22;
if(y < 1)y = 1;
}
if(screen == 5)
{
if(x > 21)x = 21;
if(x < 1)x= 1;
if(y > 52)y = 52;
if(y < 1)y = 1;
}
if(screen == 6)
{
if(x > 51)x = 51;
if(x < 1)x = 1;
if(y > 52)y = 52;
if(y < 1)y = 1;
}
if(arduboy.justPressed(DOWN_BUTTON))
{
y = y + 10;
}
if(arduboy.justPressed(UP_BUTTON))
{
y = y - 10;
}
if(arduboy.justPressed(LEFT_BUTTON))
{
x = x -10;
}
if(arduboy.justPressed(RIGHT_BUTTON))
{
x = x + 10;
}
if(arduboy.justPressed(B_BUTTON))
{
gamestate = 1;
}
arduboy.drawBitmap(x,y,heart,8,8,WHITE);
}
if(heart_type == 3)
{
delay(20);
arduboy.drawBitmap(x,y,heart,8,8,WHITE);
if(screen == 1)
{
if(x > 41)x = 41;
if(x < 1)x = 1;
if(y > 7)y = 7;
if(y < 1)y = 1;
}
if(screen == 2)
{
if(x > 16)x =16;
if(x < 1)x = 1;
if(y > 32)y = 32;
if(y < 1)y = 1;
}if(screen == 3)
{
if(x > 41)x = 41;
if(x < 1)x = 1;
if(y > 30)y = 30;
if(y < 1)y = 1;
}
if(screen == 4)
{
if(x > 51)x = 51;
if(x < 1)x = 1;
if(y >12)y = 12;
if(y < 1)y = 1;
}
if(screen == 5)
{
if(x > 21)x = 21;
if(x < 1)x= 1;
if(y > 42)y = 42;
if(y < 1)y = 1;
}
if(screen == 6)
{
if(x > 51)x = 51;
if(x < 1)x = 1;
if(y > 42)y = 42;
if(y < 1)y = 1;
}
if(jump == 0)
{
y = y + velocity;

velocity++;
if(velocity > 10)
{
velocity = 10;
}
}
if(arduboy.justPressed(A_BUTTON) and jump == 0)
{
jump = 1;
velocity = 8;
}
if(jump == 1)
{
y = y - velocity;
velocity--;
}
if(velocity < 0)
{
velocity = 0;
jump = 0;
}
if(arduboy.pressed(LEFT_BUTTON))
{
x--;
}
if(arduboy.pressed(RIGHT_BUTTON))
{
x++;
}
if(arduboy.justPressed(B_BUTTON))
{
gamestate = 1;
}
}
arduboy.fillRect(enemyx,enemyy,16,16,WHITE);
arduboy.fillRect(enemyx+1,enemyy+1,14,14,BLACK);
if(enemycount == 0)
{
rnd_x = x;
rnd_y = y;
count = 1;
}
if(enemycount == 1)
{
if(enemyx > rnd_x){enemyx++;}
if(enemyx < rnd_x){enemyx--;}
if(enemyy > rnd_y){enemyy++;}
if(enemyy < rnd_y){enemyy--;}
}
if(enemyx > rnd_x and enemyy > rnd_y)
{
enemycount = 0;
}
arduboy.display();
break;
case 5:
arduboy.clear();
arduboy.pollButtons();
arduboy.fillRect(enemyx,enemyy,16,16,WHITE);
arduboy.fillRect(enemyx+1,enemyy+1,14,14,BLACK);
if(arduboy.pressed(LEFT_BUTTON))
{
enemyx--;
}
if(arduboy.pressed(RIGHT_BUTTON))
{
enemyx++;
}
if(arduboy.pressed(UP_BUTTON))
{
enemyy--;
}
if(arduboy.pressed(DOWN_BUTTON))
{
enemyy++;
}
if(arduboy.justPressed(B_BUTTON))
{
gamestate = 1;
}

arduboy.display();

}}
//Bitmaps

#ifndef BITMAPS_H
const unsigned char undertale[] PROGMEM
=
{
0x00,0xFC,0xFE,0xFF,0xFF,0xFE,0xFC,0xF0,0xF0,0xFC,0xFE,0xFF,0xFF,0xFE,0xFC,0x00,
0x00,0x01,0x01,0x07,0x07,0x1F,0x1F,0x7F,0x7F,0x1F,0x1F,0x07,0x07,0x01,0x01,0x00,

};
const unsigned char heart[] PROGMEM
=
{
0x0E,0x1F,0x3F,0x7E,0x7E,0x3F,0x1F,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

};
#endif
``````

You might want to edit that to wrap it in a code block so it’s formatted properly and doesn’t eat two screens.

Also if it’s not in a code block the forum formats it in a way that prevents it from compiling if you copy and paste it.
(It converts the normal quotes into different quote mark characters and does some other weird that I can’t quite figure out the extent of. At minimum it seems to have deleted some minus signs.)

I managed to edit it into a state where it would compile so I managed to get a better perspective of what your game is like.

Rather than editing your existing file (because to be honest I struggled to read it), would you be ok with me posting a working demo of just the enemies being added and then you can ask questions about it and try to integrate it into your existing code?

Yes please. Sorry I write code very messy😬

It’s understandable, everyone writes messy code sometimes.
Being able to keep code ‘clean’ is something that takes a lot of practise.

I apologise for using lots of techniques you won’t have learnt about yet, but if there’s anything you’re particularly curious about I’ll be sure to do my best to explain.

The controls are basically what you described, direction buttons move the cursor, A adds an enemy if you’re on an empty space and removes an enemy if it’s on top of an enemy.
(This also means enemies can’t overlap.)
The maximum number ofenemies is 10 and there’s an indicator in the top left showing how many enemies have been placed and how many can be placed.

Enemy.h

``````#pragma once

class Enemy
{
private:
uint8_t x;
uint8_t y;

public:
Enemy(void) = default;

Enemy(const uint8_t & x, const uint8_t & y)
{
this->x = x;
this->y = y;
}

uint8_t getX(void)
{
return this->x;
}

uint8_t getY(void)
{
return this->y;
}

uint8_t getWidth(void)
{
return 16;
}

uint8_t getHeight(void)
{
return 16;
}
};
``````

EnemyList.h

``````#pragma once

#include "Enemy.h"

template<int N>
struct EnemyList
{
private:
Enemy array[N];
uint8_t next;

public:
// Returns the number of Enemys currently in the list
uint8_t getCount(void) const { return next; }

// Returns the maximum number of Enemys the list can hold
uint8_t getCapacity(void) const { return N; }

// Returns true if the list is full
bool isFull(void) const { return getCount() == getCapacity(); }

// Returns true if the list is empty
bool isEmpty(void) const { return getCount() == 0; }

// Clears the list (by cheating)
void clear(void) { next = 0; }

// Returns true if the Enemy was added
// Returns false if the list is already full
{
if(this->isFull())
return false;

array[next] = enemy; // put the Enemy in the array
++next; // increment the next index
return true;
}

// Returns true if the Enemy was removed
// Returns false if the index was invalid
bool removeAt(uint8_t index)
{
if(index >= next)
return false;

--next; // decrement next index
for(int i = index; i < next; ++i) // shuffle everything down
array[i] = array[i + 1];
return true;
}

// These are for indexing the list
// Be careful, these don't check if the index is valid
Enemy & operator[](uint8_t index) { return array[index]; }
const Enemy & operator[](uint8_t index) const { return array[index]; }
};
``````

Demo.ino

``````#include <Arduboy2.h>

#include "Enemy.h"
#include "EnemyList.h"
constexpr const static uint8_t ScreenWidth = WIDTH;
constexpr const static uint8_t ScreenHeight = HEIGHT;

constexpr const static uint8_t CursorWidth = 16;
constexpr const static uint8_t CursorHeight = 16;

uint8_t CursorX;
uint8_t CursorY;

EnemyList<10> enemies;

Arduboy2 arduboy;

void setup()
{
arduboy.begin();
}

void loop()
{
if(!arduboy.nextFrame())
return;

update();
render();
}

void update(void)
{
arduboy.pollButtons();
if(arduboy.pressed(LEFT_BUTTON))
{
if(CursorX > 0)
--CursorX;
}
if(arduboy.pressed(RIGHT_BUTTON))
{
if(CursorX + CursorWidth < ScreenWidth)
++CursorX;
}
if(arduboy.pressed(UP_BUTTON))
{
if(CursorY > 0)
--CursorY;
}
if(arduboy.pressed(DOWN_BUTTON))
{
if(CursorY + CursorHeight < ScreenHeight)
++CursorY;
}
if(arduboy.justPressed(A_BUTTON))
{
Rect cursorRect { CursorX, CursorY, CursorWidth, CursorHeight };

bool foundEnemy = false;

// Loops through every enemy in the list
for(uint8_t i = 0; i < enemies.getCount(); ++i)
{
Rect enemyRect { enemies[i].getX(), enemies[i].getY(), enemies[i].getWidth(), enemies[i].getHeight() };

// Removes the first enemy that's colliding with the cursor
// If more than one enemy is under the cursor,
// the oldest one will be removed
if(arduboy.collide(cursorRect, enemyRect))
{
enemies.removeAt(i);
foundEnemy = true;
break;
}
}

// If the cursor wasn't on top of an enemy, add a new enemy
if(!foundEnemy)
{
}
}
if(arduboy.justPressed(B_BUTTON))
{
}
}

void render(void)
{
arduboy.clear();

// Draw all the enemies as filled boxes for now
for(uint8_t i = 0; i < enemies.getCount(); ++i)
{
arduboy.fillRect(enemies[i].getX(), enemies[i].getY(), enemies[i].getWidth(), enemies[i].getHeight());
}

// Draw cursor
arduboy.drawRect(CursorX, CursorY, CursorWidth, CursorHeight);

// Write the number of enemies on the field/available
arduboy.setCursor(0, 0);
arduboy.print(enemies.getCount());
arduboy.print('/');
arduboy.print(enemies.getCapacity());

arduboy.display();
}``````

@Cody17, As @Pharap recommended, I’ve edited your post of the code to wrap it as a code block.

In the future, you should do this yourself as follows:
Before the first line of code add a line consisting of three backticks and the letters cpp like so:

`````````cpp
``````

After the last line of code add a line containing three backticks:

`````````
``````

So when adding a code block to a post, it would look like this in the editing window:

`````````cpp
//main

#include <Arduboy2.h>
#include "Bitmaps.h"
Arduboy2 arduboy;
(the rest of the code ...)
`````````
2 Likes