IKD - Atari Combat remake

Use this forum to share and discuss Uzebox games and demos.
Post Reply
User avatar
danboid
Posts: 1937
Joined: Sun Jun 14, 2020 12:14 am

Re: IKD - Atari Combat remake

Post by danboid »

I have now added a menu to IKD that lets you select the maze. Eventually you will be able to enable or disable bouncy bullets from the menu. I want to add a title screen image too and hopefully I'll also be able to improve the tank/wall collision code which seems as bloaty as it is wonky.
User avatar
danboid
Posts: 1937
Joined: Sun Jun 14, 2020 12:14 am

Re: IKD - Atari Combat remake

Post by danboid »

This is a log of my first ChatGPT session. I wanted it to suggest a way to implement a new feature in my Uzebox game, IKD.

At first I tried to paste the entire main C source code file of my game followed by my question but it was too big to be accepted by ChatGPT at ~950 lines of code so I removed the bloated tank/wall collision code and that made it short enough to be accepted by ChatGPT at ~450 lines. I pasted most of IKD.c, everything except/ up to the tank/wall collision function, into ChatGPT and this is how it went:

Add a new menu option to this C code to make the bullets bounce of the walls

This appears to be a code file written in the C programming language for a game called IKD (presumably an acronym for something). The code appears to define several constants and variables, as well as several functions that are used to initialize and control the game. It looks like the game involves two tanks that can move around and shoot at each other, and the code defines data structures to represent the state of these tanks and their bullets. It also appears that the game includes a main menu, and there are functions defined for rendering and interacting with this menu. Do you have any specific questions about this code?
I would like a new menu option added to make the tanks bullets bounce off the walls

To add a new menu option to the main menu that allows the player to toggle whether the tanks' bullets should bounce off the walls, you can try the following steps:

Declare a new global variable that will store the current state of the bounce feature, initialized to false. For example:

bool bulletsBounce = false;

Add a new entry to the menu_opts array that represents the new menu option. You can use the TextOut function to display the string "Bounce" at the appropriate position on the screen. For example:

menu_opts[3] = 27;
TextOut(11, 15, "Bounce");

In the processMainMenu function, add a case to the switch statement that handles the input for the new menu option. When this option is selected, toggle the value of the bulletsBounce variable and update the screen to reflect the new state of the bounce feature. For example:

case 27:
bulletsBounce = !bulletsBounce;
if (bulletsBounce) {
TextOut(11, 15, "Bounce");
} else {
TextOut(11, 15, " ");
}
break;

In the processBullets function, add a check for the value of the bulletsBounce variable before allowing the bullets to collide with the walls. If bulletsBounce is true, you will need to modify the vX and vY components of the bullet's velocity vector to reflect the bounce. One way to do this is to negate the component that is colliding with the wall (for example, if the bullet hits a vertical wall, negate the vX component). You may also want to add some code to reduce the magnitude of the velocity vector slightly after each bounce to simulate friction or air resistance. For example:

if (p1_bullet.x < 0 || p1_bullet.x > 128 ||
p1_bullet.y < 0 || p1_bullet.y > 128) {
if (bulletsBounce) {
if (p1_bullet.x < 0 || p1_bullet.x > 128) {
p1_bullet.vX = -p1_bullet.vX * 0.9;
}
if (p1_bullet.y < 0 || p1_bullet.y > 128) {
p1_bullet.vY = -p1_bullet.vY * 0.9;
}
} else {
p1_bullet.active = false;
}
}

I hope this helps! Let me know if you have any questions or if you need further assistance.
This is a game written in C for the Uzebox games console.

I apologize for the oversight. The Uzebox is a small, open source game console that uses an Atmel AVR microcontroller as its main processing unit. It was designed to be simple and easy to program, and it supports a wide range of classic gaming hardware features such as sprites, tilemaps, and sound channels. The code you posted appears to be written in C and makes use of several functions and constants provided by the Uzebox software development kit (SDK). The game appears to be a reimplementation of the tank game from Atari's Combat, with some additional features and mechanics. Do you have any specific questions about the code or the Uzebox platform that I can help with?
IKD is an acronym for I Kill Death

I see, thank you for clarifying the acronym. It looks like the game is a two-player tank combat game, where each player controls a tank and tries to destroy the other player's tank by shooting bullets at them. The game appears to have several features such as different maze layouts, a main menu, scorekeeping, and the ability to adjust the angle and velocity of the tanks' bullets. It also looks like there is a bounce feature that allows the bullets to bounce off the walls of the maze, which can be enabled or disabled through the main menu. Is there anything else I can help with?
There is no TextOut function in the Uzebox API. The correct way to print the new menu item would be to use a statement like:

Print(10,26,PSTR("Bounce"));

Thank you for pointing out the error in my previous suggestion. You are correct that the TextOut function is not part of the Uzebox API. Instead, you can use the Print function to print strings stored in program memory (flash memory) to the screen. The Print function takes three arguments: the X and Y coordinates of the top-left corner of the text, and a pointer to a null-terminated string stored in program memory. To print the string "Bounce" at position (10, 26) on the screen, you can use a statement like this:

Print(10, 26, PSTR("Bounce"));

Note that the PSTR macro is used to convert the string literal to a pointer to program memory.

I apologize for the mistake in my previous suggestion. I hope this helps! Let me know if you have any other questions or if you need further assistance.
User avatar
danboid
Posts: 1937
Joined: Sun Jun 14, 2020 12:14 am

Re: IKD - Atari Combat remake

Post by danboid »

Whilst I wasn't quite able to copy/paste its suggestions and have them solve my problem, what it suggested was a good outline of the sort of steps you'd take to adding bouncy bullets and it managed chuck in a suggestion that I'd not requested by adding wind velocity. I'm definitely impressed.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: IKD - Atari Combat remake

Post by Artcfox »

I haven't messed around with ChatGPT yet, but that's pretty freaky!
User avatar
danboid
Posts: 1937
Joined: Sun Jun 14, 2020 12:14 am

Re: IKD - Atari Combat remake

Post by danboid »

I was amazed. Yesterday was my birthday so I waited until my birthday to give it a go and it reminds me of my first time using a search engine or whatever big turning point you wish to compare it to but this looks like this could be the biggest advance in computing in some time. Seems I might've been the first to request it work on a Uzebox game.

I'm going to use it to add comments for me and see what else it can improve for me.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: IKD - Atari Combat remake

Post by Artcfox »

That is pretty cool. I did wonder when I saw other people's programming examples if it would be able to handle something on the Uzebox, but I wouldn't even know how to get started using it, so I'm glad that you tried it and gave us a full report.

It does seem like a pretty big advancement, though from what I've read, it's just a predictive text engine. What blows my mind is how capable just that is, and it makes me wonder what's going to happen if we ever get artificial general intelligence, something that can learn and reason the way a human does, rather than just pick the next most probable word based on a training dataset.

Also, Happy (belated) Birthday!
User avatar
danboid
Posts: 1937
Joined: Sun Jun 14, 2020 12:14 am

Re: IKD - Atari Combat remake

Post by danboid »

Thanks Artcfox!

Today I finally made some progress on one of the final features I want to add to this, bouncy bullets. I had to add vX and vY to the tankstruct so that the tanks velocity is stored and calculated independently of the bullets.

I've enabled "bouncy bullets" for both players by default currently but they're "fake bouncy" for want of a less suggestive phrase. They currently only bounce back and forth between 2 walls:

See line 310 of IKD.c:

Code: Select all

else if (GetTile(p1_bullet.gridX, p1_bullet.gridY) == 0x25) {
      // Fake bouncy bullet
      p1_bullet.vX = -p1_bullet.vX * 0.9;
      p1_bullet.vY = -p1_bullet.vY * 0.9;
    }
How might I improve this basic bouncy bullet code so that it will deflect off multiple surfaces and not just ping-pong between 2 walls?
Last edited by danboid on Fri Jan 06, 2023 7:51 pm, edited 1 time in total.
User avatar
danboid
Posts: 1937
Joined: Sun Jun 14, 2020 12:14 am

Re: IKD - Atari Combat remake

Post by danboid »

ChatGPT to the rescue?

Me: How might I improve processBullets() so that the bullets will deflect off multiple surfaces and not just ping-pong between 2 walls?

GPT3: To make the bullets deflect off multiple surfaces, you will need to update the processBullets() function to check for collisions with all walls in the level, not just the two adjacent walls.

One way to do this would be to use a 2D array to represent the level layout, with each element in the array representing a tile on the screen. You can then use the bullet's position and velocity to determine which tiles it will pass through during each frame. For each tile that the bullet will pass through, you can check if that tile is a wall or not, and if it is, you can calculate the new velocity for the bullet based on the angle of the wall and the direction the bullet was coming from.

Here is some pseudocode that demonstrates this approach:

Code: Select all

void processBullets() {
  for each bullet {
    int startX = bullet.x / 8; // convert from pixels to tile units
    int startY = bullet.y / 8;
    int endX = (bullet.x + bullet.vX) / 8;
    int endY = (bullet.y + bullet.vY) / 8;

    // Check if the bullet is moving horizontally or vertically
    if (startX == endX) {
      // Bullet is moving vertically
      int direction = (bullet.vY > 0) ? 1 : -1;
      for (int y = startY; y != endY; y += direction) {
        if (level[y][startX] == WALL) {
          // Collision with vertical wall, reverse Y velocity
          bullet.vY = -bullet.vY;
          break;
        }
      }
    } else {
      // Bullet is moving horizontally
      int direction = (bullet.vX > 0) ? 1 : -1;
      for (int x = startX; x != endX; x += direction) {
        if (level[startY][x] == WALL) {
          // Collision with horizontal wall, reverse X velocity
          bullet.vX = -bullet.vX;
          break;
        }
      }
    }

    // Update bullet position based on new velocity
    bullet.x += bullet.vX;
    bullet.y += bullet.vY;
  }
}
This approach will allow the bullets to deflect off multiple walls and surfaces in the level.

https://github.com/danboid/IKD/issues/1
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: IKD - Atari Combat remake

Post by Artcfox »

Nice! The bouncy bullets you describe remind me of the mirrors and beam splitter in my Laser Puzzle/Laser Puzzle 2 game that end up redirecting and splitting the laser beam. At each square, a laser beam could be entering and/or exiting and mirrors or beam splitters could be placed on any of the 45 degree angles on a square, so I used 8 bits to represent the state at each grid position. Though, unless your tanks shoot lasers, you probably just need the logic that determines where it goes next, unless you want to leave a vapor trail behind the bullets.

Code: Select all

/* Each square may have a laser beam going in and/or out in any direction
      IN   OUT
   0b 0000 0000
       \\\\ \\\\__ top
        \\\\ \\\__ bottom
         \\\\ \\__ left
          \\\\ \__ right
           \\\\
            \\\\__ top
             \\\__ bottom
              \\__ left
               \__ right
*/
#define D_OUT_T 1
#define D_OUT_B 2
#define D_OUT_L 4
#define D_OUT_R 8

#define D_IN_T 16
#define D_IN_B 32
#define D_IN_L 64
#define D_IN_R 128

// The bitmap of where the laser is, and which direction(s) it is traveling
uint8_t laser[5][5] = {
  {  0,  0,  0,  0,  0 },
  {  0,  0,  0,  0,  0 },
  {  0,  0,  0,  0,  0 },
  {  0,  0,  0,  0,  0 },
  {  0,  0,  0,  0,  0 },
};
Full code here.
User avatar
danboid
Posts: 1937
Joined: Sun Jun 14, 2020 12:14 am

Re: IKD - Atari Combat remake

Post by danboid »

It was getting too late when GPT gave me its solution for me to being doing any coding and I've only tried to implement it today.

My questions:

Code: Select all

int p1_bullet.direction = (p1_bullet.vY > 0) ? 1 : -1;
Is that a valid ternary int definition in C?

Code: Select all

for (int y = p1_bullet.startY; y != p1_bullet.endY; y += p1_bullet.direction) {
Would a for statement like that be valid C and do what it's trying to tell me to do?

GPT introduced a new theoretical struct member for the bullet, .direction, when my bullet code doesn't currently have a stored, pre-calculated direction. How do you think it presumes we are working with direction? IKD has 16 possible directions for the tanks and bullets but as far as the wall collision code is concerned there are only 8 directions. I suspect 8 directions should suffice to provide enough detail for the bullets direction or can we get away with less?

Where GPT sets the startX/startY and endX/endY in the psedocode, I do that in processTank1() or processTank2() when the users press fire instead of ProcessBullets().

Then the GPT pseudocode suggests:

Code: Select all

if (level[y][startX] == WALL) {
level is a nonsense function but it might potentially translate into GetTile()?:

Code: Select all

if (GetTile(y,p1_bullet.startX) == 0x25) {
Where 0x25 is the hex value of the wall tile. I don't see how that could work tho. I think I need to devise my own way to detect if a wall is horizontal or vertical.

Do you think this pseudocode could be made to work ArtcFox, if adapted properly to my game code?

Something like this (only potentially legit C alert), maybe?:

Code: Select all

if (p1_bullet.startX == p1_bullet.endX) {
      // Bullet is moving vertically
      p1_bullet.direction = (p1_bullet.vY > 0) ? 1 : -1;
      for (int y = p1_bullet.startY; y != p1_bullet.endY; y += p1_bullet.direction) {
        if (GetTile(y,p1_bullet.startX) == 0x25) {
          // Collision with vertical wall, reverse Y velocity
          p1_bullet.vY = p1_bullet.vY * -1;
          break;
        }
      }
    } else {
      // Bullet is moving horizontally
      p1_bullet.direction = (p1_bullet.vX > 0) ? 1 : -1;
      for (int x = p1_bullet.startX; x != p1_bullet.endX; x += p1_bullet.direction) {
        if (GetTile(p1_bullet.startY,x) == 0x25) {
          // Collision with horizontal wall, reverse X velocity
          p1_bullet.vX = p1bullet.vX * -1;
          break;
        }
        // Update bullet position based on new velocity
    p1_bullet.x += p1_bullet.vX;
    p1_bullet.y += p1_bullet.vY;
      }
    }

Post Reply