Several newb questions
Re: Several newb questions
I think that if we are going to include games in the official repo, those games need to work with the latest Uzebox kernel, we don't want multiple copies of different kernel versions in the official repo. It looks like the code for Pong is intended for a really old version of the Uzebox kernel, and removing the deps/ directory will allow the "make" to work, but not if you then run "make clean" followed by "make".
I tried pointing it to the latest kernel, but that fails too, because according to the Makefile, Pong uses Video Mode 3, but it's calling API functions like DrawMap which are meant for Video Mode 1. I changed all of those calls, and made all of the arrays the correct type, but when I played the game the sounds were glitchy and the gameplay was different from the original. I put everything back, and then left it pointing at the original kernel it includes, and added const to the PROGMEM array it complains about, but some of the sounds and gameplay are different from the released Pong.hex and Pong.uze files, so now I'm not even sure that that source code matches up with the released game.
I think that the Pong game does show how to use sprites though, but you can also check the API documentation for examples to get an idea of how to use the different functions available. For isntance: http://uzebox.org/wiki/Function_MapSprite
Here is a link to the top level API docs: http://uzebox.org/wiki/API_Functions
Oh, and The Uzebox Mode 3 with Scrolling Guide I linked you to isn't a video, it's a PDF that has diagrams and example source code, and it links to follow-along mini tutorials on github that you can clone and start modifying.
I tried pointing it to the latest kernel, but that fails too, because according to the Makefile, Pong uses Video Mode 3, but it's calling API functions like DrawMap which are meant for Video Mode 1. I changed all of those calls, and made all of the arrays the correct type, but when I played the game the sounds were glitchy and the gameplay was different from the original. I put everything back, and then left it pointing at the original kernel it includes, and added const to the PROGMEM array it complains about, but some of the sounds and gameplay are different from the released Pong.hex and Pong.uze files, so now I'm not even sure that that source code matches up with the released game.
I think that the Pong game does show how to use sprites though, but you can also check the API documentation for examples to get an idea of how to use the different functions available. For isntance: http://uzebox.org/wiki/Function_MapSprite
Here is a link to the top level API docs: http://uzebox.org/wiki/API_Functions
Oh, and The Uzebox Mode 3 with Scrolling Guide I linked you to isn't a video, it's a PDF that has diagrams and example source code, and it links to follow-along mini tutorials on github that you can clone and start modifying.
Re: Several newb questions
You're totally right that all the included examples should build on the current kernel. I had noticed that Pong wasn't building after I did a `make clean` but that's where I stopped yesterday, presuming it would just be an issue with the makefile. I was going to look into cleaning Pong up and integrating it into the UB repo build today although I would've only encountered all those issues you described.
How is the gameplay different in your port of pong to the newer kernel? We can fix the sounds easy enough and as long as:
* The ball bounces off the paddles and walls
* The correct players score increments when the ball goes into the goal
If those functions still work then surely we have a valid pong remake? It need not be 100% faithful to either the arcade nor the original UB remake. The quality of the game actually doesn't matter, it just has to build and run with the current kernel. The UB repo would greatly benefit from having an example like this as a middle ground example between the Hello world and Arkanoid, Loderunner and Super Mario examples etc.
This brings me onto a question I'd not yet asked which has been highlighted excellently by this pong issue. It seems Uzebox is the "Linux of game consoles" but unfortunately along with the open nature UB has also replicated Linux's crap backwards compatibility, at least on the source code / API level, as evidenced by my lack of success at getting (old) UB games to build.
So whose fault is this, mainly? GCC's or the UB devs or both? Is there any hope that things will improve going forward so that code I write against the current kernel may still build against the UB kernel in 2025? Has the kernel / API stabilised? Are more big changes in the pipeline that would cause more breakage?
I shall have a look at this PDF shortly Matt, thanks!
How is the gameplay different in your port of pong to the newer kernel? We can fix the sounds easy enough and as long as:
* The ball bounces off the paddles and walls
* The correct players score increments when the ball goes into the goal
If those functions still work then surely we have a valid pong remake? It need not be 100% faithful to either the arcade nor the original UB remake. The quality of the game actually doesn't matter, it just has to build and run with the current kernel. The UB repo would greatly benefit from having an example like this as a middle ground example between the Hello world and Arkanoid, Loderunner and Super Mario examples etc.
This brings me onto a question I'd not yet asked which has been highlighted excellently by this pong issue. It seems Uzebox is the "Linux of game consoles" but unfortunately along with the open nature UB has also replicated Linux's crap backwards compatibility, at least on the source code / API level, as evidenced by my lack of success at getting (old) UB games to build.
So whose fault is this, mainly? GCC's or the UB devs or both? Is there any hope that things will improve going forward so that code I write against the current kernel may still build against the UB kernel in 2025? Has the kernel / API stabilised? Are more big changes in the pipeline that would cause more breakage?
I shall have a look at this PDF shortly Matt, thanks!
Re: Several newb questions
I think the kernel has been stable for quite some time, and probably some individual games have done things in a nonstandard way on occasion. I for one am guilty of having source code relying on hacked kernels because I needed extra/different functionality. Over the course of the years, the kernel pretty well added all the things needed even for advanced usage. I would call it bit rot, but not too bad considering the loose nature of it all. It would be nice to fix all games.
Pong would be a good game to have in the repo for sure. I believe the first video game I ever really completed was a Pong clone, with huge cheater AI It is fairly easy to wrap your head around the entirety of the game, versus more advanced ones to start with.
Pong would be a good game to have in the repo for sure. I believe the first video game I ever really completed was a Pong clone, with huge cheater AI It is fairly easy to wrap your head around the entirety of the game, versus more advanced ones to start with.
Re: Several newb questions
Artcfox:
Could you upload your updated pong code please?
I've had a busy week but I'll get some time to play with UB stuff this weekend.
Could you upload your updated pong code please?
I've had a busy week but I'll get some time to play with UB stuff this weekend.
Re: Several newb questions
Attached is a quick changing of some things in the Pong code to try to get them to work with the correct APIs. Extract it in your directory, so the path to its Makefile is
Under the "See Also" section of this page:
http://uzebox.org/wiki/Video_Modes#Mode_3
is where I learned how to use sprites on the Uzebox.
Good luck!
Code: Select all
uzebox/MY_GAMES/
Code: Select all
uzebox/MY_GAMES/Pong-mode3/default/Makefile
http://uzebox.org/wiki/Video_Modes#Mode_3
is where I learned how to use sprites on the Uzebox.
Good luck!
- Attachments
-
- Pong-mode3.zip
- (273.84 KiB) Downloaded 476 times
Re: Several newb questions
Thanks for sharing your updated pong port Artcfox!
I can confirm this code still builds fine after a `make clean` with the current kernel for me, and it's less than 200 lines so this seems like the perfect example to me but as you say a couple of the sounds effects need tweaking. You should let me fix that, then maybe we can push it into the repo? I'm hoping to read your PDF later tonight.
I can confirm this code still builds fine after a `make clean` with the current kernel for me, and it's less than 200 lines so this seems like the perfect example to me but as you say a couple of the sounds effects need tweaking. You should let me fix that, then maybe we can push it into the repo? I'm hoping to read your PDF later tonight.
Re: Several newb questions
Hi ArtcFox!
I have fixed the two dodgy sound FX in pong by using the following for patches.inc:
The pitch values were invalid (-50 when it has to be between 0 and 126) nor did it like PC_NOTE_UP.
I have fixed the two dodgy sound FX in pong by using the following for patches.inc:
Code: Select all
const char patch00[] PROGMEM ={
0,PC_ENV_VOL,0xff,
0,PC_PITCH, 50,
3,PC_ENV_VOL,0x00,
0,PATCH_END
};
const char patch01[] PROGMEM ={
0,PC_ENV_VOL,0xff,
0,PC_NOTE_DOWN,20,
2,PC_ENV_VOL,0x00,
0,PATCH_END
};
const char patch02[] PROGMEM ={
0,PC_ENV_VOL,0xff,
0,PC_PITCH, 50,
13,PC_ENV_VOL,0x00,
0,PATCH_END
};
const struct PatchStruct PongPatch[] PROGMEM = {
{0,NULL,patch00,0,0},
{0,NULL,patch01,0,0},
{0,NULL,patch02,0,0},
};
Re: Several newb questions
Nice find!
Re: Several newb questions
Here's my first UB coding experiment which moves a sprite around the screen with the joystick.
This is the sort of example demo I was hoping for in the repo, although done proper. I'd like to know what an experienced C/UB programmer would do differently as no doubt this code can be improved in several ways
This is the sort of example demo I was hoping for in the repo, although done proper. I'd like to know what an experienced C/UB programmer would do differently as no doubt this code can be improved in several ways
Code: Select all
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <stdlib.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <uzebox.h>
#include "data/tileset.inc"
int btnPrev = 0; // Previous button
int btnHeld = 0; // buttons that are held right now
int btnPressed = 0; // buttons that were pressed this frame
int btnReleased = 0; // buttons that were released this frame
struct Playerstruct{
unsigned char x;
unsigned char y;
};
struct Playerstruct Player;
int main()
{
ClearVram();
SetTileTable(tileset);
Player.x = 100;
Player.y = 100;
MoveSprite(3,Player.x,Player.y,1,1);
while(1){
WaitVsync(1);
btnHeld = ReadJoypad(0);
btnPressed = btnHeld & (btnHeld ^ btnPrev);
btnReleased = btnPrev & (btnHeld ^ btnPrev);
if(btnHeld & BTN_RIGHT){
MoveSprite(3,Player.x+=3,Player.y,1,1);
}
if(btnHeld & BTN_LEFT){
MoveSprite(3,Player.x-=3,Player.y,1,1);
}
if(btnHeld & BTN_UP){
MoveSprite(3,Player.x,Player.y-=3,1,1);
}
if(btnHeld & BTN_DOWN){
MoveSprite(3,Player.x,Player.y+=3,1,1);
}
btnPrev = btnHeld;
}
}
Re: Several newb questions
Nice!
I don't see the call to:
nor do I see the call to:
which you would use when calling
Have a read through this page: http://uzebox.org/wiki/Video_Mode_3 specifically the "Sprites structure" section and the following "Using sprites" section.
It looks like you just want to move a single sprite, so you can just set that sprite's x and y coordinate directly in the sprite structure:
The MapSprite2 and MoveSprite functions are helper functions for when you have a megasprite (an object made up of multiple smaller sprites arranged in a grid pattern). It doesn't look like you have that, since the size is 1x1, so you can get away with just setting the sprites structure manually.
I typically use a structure to manage all of the button stuff:
and then in the beginning of my program I do:
And when I want to read them and act:
Another thing that I always always do is use types that have the size in them: uint8_t, int8_t, uint16_t, int16_t, etc... That way you always know exactly what size you're getting, and you can prototype or unit test the same code on your dev machine, and get the same results.
You'll find things like this:
are not only more readable, but will compile down to more efficient machine code than if you had written it as:
because in the first, the compiler knows you are only interested in the first 8 bits, and so it only needs to compare those. In the second, the result of that math is stored internally as a 16 bit integer, and so the comparison is performed on all 16 bits.
I don't see the call to:
Code: Select all
SetSpritesTileBank(0, mysprites);
Code: Select all
MapSprite2
Code: Select all
MoveSprite
It looks like you just want to move a single sprite, so you can just set that sprite's x and y coordinate directly in the sprite structure:
Code: Select all
sprites[3].x = Player.x;
sprites[3].y = Player.y;
I typically use a structure to manage all of the button stuff:
Code: Select all
typedef struct {
uint16_t held;
uint16_t prev;
uint16_t pressed;
uint16_t released;
} __attribute__ ((packed)) BUTTON_INFO;
Code: Select all
BUTTON_INFO buttons;
memset(&buttons, 0, sizeof(BUTTON_INFO));
Code: Select all
buttons.prev = buttons.held;
buttons.held = ReadJoypad(0);
buttons.pressed = buttons.held & (buttons.held ^ buttons.prev);
buttons.released = buttons.prev & (buttons.held ^ buttons.prev);
if (buttons.pressed & BTN_DOWN) {
...
}
if (buttons.pressed & BTN_UP) {
...
}
You'll find things like this:
Code: Select all
uint8_t hmod = ((tx - BOARD_START_X) % BOARD_H_SPACING);
if (hmod < TOKEN_WIDTH)
Code: Select all
if (((tx - BOARD_START_X) % BOARD_H_SPACING) < TOKEN_WIDTH)