a (try) version of pong and solved video driver issue

I have never read an implementation of Pong and have wanted to work on it for a long time.
In principle, it works the way I thought it would. At times strange effects occur, but on the whole it is stable.
After the weekend, I can continue to take care of it.
At this version of pong the propeller plays against itself. The paddle position is calculated to hit the ball.
An expansion to several cogs is planned.
nice weekend
Reinhard
In principle, it works the way I thought it would. At times strange effects occur, but on the whole it is stable.
After the weekend, I can continue to take care of it.
At this version of pong the propeller plays against itself. The paddle position is calculated to hit the ball.
An expansion to several cogs is planned.
nice weekend
Reinhard
Comments
but I have not a long time observed.
LINE175 if(ym < 20 || ym > 470)
I've modified your pong code to speed it up and it runs smoother now. Not so much flicker.
You can use the fillCircle routine I included to draw circles of any colour and size, as well as
syncing up to the blanking period to avoid tearing etc. Clearing the entire screen
is slow, so you can erase just the ball and paddle. Take a look at what I changed.
By the way, no need to distribute the entire video folder, just p2videodrv.spin2 is enough.
Cheers,
Roger.
* +-------------------------------------------------------------------- | TERMS OF USE: MIT License +-------------------------------------------------------------------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------- */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <math.h> #include <propeller2.h> #define P2_TARGET_MHZ 160 #include "sys/p2es_clock.h" #define BAUD 230400 // screen size #define SCRN_WIDTH 640 #define SCRN_HEIGHT 480 // VGA definitions #define VGA_BASE_PIN 48 #define VGA_VSYNC_PIN (VGA_BASE_PIN + 4) // enough room for a scanline at full colour bit depth #define LINEBUFSIZE (1920*4) // RGBI8 colortable with full luminance #define ORANGE 0b000_11111 #define BLUE 0b001_11111 #define GREEN 0b010_11111 #define CYAN 0b011_11111 #define RED 0b100_11111 #define MAGENTA 0b101_11111 #define YELLOW 0b110_11111 #define WHITE 0b111_11111 #define BLACK 0 // the video object struct __using("video/p2videodrv.spin2") vid; // space for video driver display and region info int display1[14]; int first[14]; // the actual frame and line buffer char frameBuffer[SCRN_WIDTH*SCRN_HEIGHT]; int lineBuffer[LINEBUFSIZE]; void Setup_Video() { vid.initDisplay(@display1, vid.VGA, VGA_BASE_PIN, VGA_VSYNC_PIN, vid.RGBHV, @lineBuffer, LINEBUFSIZE, 0); vid.initRegion(@first, vid.RGBI, 480, 0, 0, 0, 8, &frameBuffer[0], 0); // enable display list vid.setDisplayRegions(display1, first); } void line( int x0, int y0, int x1, int y1,int color) { int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1; int err = dx+dy, e2; /* error value e_xy */ for(;;){ /* loop */ plot(x0,y0,color); if (x0==x1 && y0==y1) break; e2 = 2*err; if (e2 > dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */ if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */ } } // routine to plot a point at screen coordinate (x,y) and color "color" void plot(int x, int y, int color) { frameBuffer[y*SCRN_WIDTH+x] = color; } void clearscreen (int color) { // clear the screen memset(frameBuffer, color , SCRN_WIDTH*SCRN_HEIGHT); } // Function for circle-generation // using Bresenham's algorithm void fillCircle(void *screen, int width, int xc, int yc, int r, int colour, int bpp) { int x, y, d; x = 0; y = r; d = 3 - 2 * r; horizLine(screen, width, xc+x, yc+y, xc-x, yc+y, colour, bpp); horizLine(screen, width, xc+x, yc-y, xc-x, yc-y, colour, bpp); horizLine(screen, width, xc+y, yc+x, xc-y, yc+x, colour, bpp); horizLine(screen, width, xc+y, yc-x, xc-y, yc-x, colour, bpp); while (x <= y) { horizLine(screen, width, xc+x, yc+y, xc-x, yc+y, colour, bpp); horizLine(screen, width, xc+x, yc-y, xc-x, yc-y, colour, bpp); horizLine(screen, width, xc+y, yc+x, xc-y, yc+x, colour, bpp); horizLine(screen, width, xc+y, yc-x, xc-y, yc-x, colour, bpp); if (d > 0) { d = d + 4 * (x - y) + 10; y--; } else d = d + 4 * x + 6; x++; } } void horizLine(void *buf, int width, int x1, int y1, int x2,int y2, int c, int bpp) { int len = x1-x2 + 1; switch(bpp) { case 8: bytefill(buf + x2+y1*width, c, len); break; case 16: wordfill(buf + 2*(x2+y1*width), c, len); break; case 32: longfill(buf + 4*(x2+y1*width), c, len); break; default: return; // unhandled for now } } void ball(int x0,int y0, int radius, int color) { /* int x,y,t; unsigned int phi = 0; for(t = 0; t < 2048; t++ ) { __asm { qrotate #5, phi getqx x getqy y }; line(x0,y0,x0+x,y0+y,WHITE); //plot(x0+x,y0+y,WHITE); phi += 0x200000} */ fillCircle(&frameBuffer, SCRN_WIDTH*8/8, x0, y0, radius, color, 8); // 8bpp } void paddle (int ym, int colour) { int yo = ym - 10; int yu = ym + 10; line(610,yu,610,yo,colour); } void main() { int i; _clkset(_SETFREQ, _CLOCKFREQ); Setup_Video(); _setbaud(BAUD); int xx = 20; int yy = 20; int dx = 5; int dy = 5; int ym = 230; float r; clearscreen(BLUE); for (;;) { // clearscreen(BLUE); ball(xx, yy, 5, WHITE); paddle(ym, WHITE); vid.waitforblanking(&display1); ball(xx,yy, 5, BLUE); paddle(ym, BLUE); //usleep(10000); xx += dx; yy += dy; // check limits if(xx < 20) dx = -dx; if(xx > 620) dx = -dx; if(yy < 20) dy = -dy; if(yy > 460) dy = -dy; // check relation from ball to paddle if ( ((xx+5) == 610) && (((yy) < (ym-10)) || ((yy) < (ym+10))) ) dx = -dx; if(dx > 0) { r = (float)((610 - xx) / dx); ym = yy + (int)r * dy; } else ym = ym; if(ym < 20 || ym > 460) ym = 230; } }
Thanks for the many tips. I am currently out of my home and will only have my hardware again on Monday. I can't wait to try your version!
Your improvements are great. I now have 2 players. Is it an advantage if I split that over 2 cogs (?).
A sound output during ping would also be interesting.
cheers
Reinhard
You might like to figure out a way to slide your paddles up and down on each side more smoothly too (interpolate) when they figure out the final position instead of jumping, although the jumping effect still looks okay.
This sort of makes a good screensaver.
Hello,
I tried to complle this sourcecode, without changes in the c-file(s), but with the newest version of flexspin.
It is unsuccessful, I get Error in the spin part.
reinhard@reinhard-TUXEDO:~/Schreibtisch/Propeller2/testbench2/pong$ /home/reinhard/Schreibtisch/Propeller2/spin2cpp-5.9.24/build/flexspin -2b -Wall pingpong.c graphictools.c
Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2023 Total Spectrum Software Inc. and contributors
Version 5.9.24-- Compiled on: Jan 13 2023
pingpong.c
|-p2videodrv.spin2
home/reinhard/Schreibtisch/Propeller2/testbench2/pong/video/p2videodrv.spin2:363: error: assignment to constant `GRAPHICS_MODE'
With the old version of fastspin I can compile:
reinhard@reinhard-TUXEDO:~/Schreibtisch/Propeller2/testbench2/pong$ /home/reinhard/Schreibtisch/Propeller2/spin2cpp-4.2.6/build/fastspin -2b -Wall pingpong.c graphictools.c
Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2020 Total Spectrum Software Inc.
Version 4.2.6 Compiled on: Jul 30 2020
pingpong.c
|-p2videodrv.spin2
graphictools.c
|-p2videodrv.spin2
memset.c
pingpong.p2asm
Done.
Program size is 347248 bytes
and download:
reinhard@reinhard-TUXEDO:~/Schreibtisch/Propeller2/testbench2/pong$ /home/reinhard/Schreibtisch/Propeller2/p2gcc-master/bin/loadp2 -b 230400 -p /dev/ttyUSB0 -t pingpong.binary
Is this a issue from flexspin or a bug in the spin - graphic driver and the new flexspin in not so tolerant like the old one?
Regards Reinhard
In all the versions of p2videodrv.spin2 that I've seen, GRAPHICS_MODE is a constant (defined in the CON section) and so if the code in line 363 really is modifying it that's an error and flexspin should never have accepted it. The p2videodrv.spin2 that comes with FlexProp (in the Multi-Language/video folder; admittedly it's an old version!) does not have any such assignment. Could you share your code?
Thank you for the fast answer.
Here is the zip file with all sources.
It is the same as I posted above.
The p2videodrv.spin2 is in the subfolder video.
Line 363 of your p2videodrv.spin2 currently reads:
byte[region][5] &= ~GRAPHICS_MODE
it should read
byte[region][5] &= !GRAPHICS_MODE
The
~
operator modifies its argument. In fact~
isn't even legal in Spin2, but flexspin accepts it as a hold-over from Spin1. I think older versions of flexspin incorrectly did not modifyx
in~x
, which may be why your code worked with the old flexspin.I remember the whole thing about incorrect
~
operator behaviours ;P@ersmith
Cool, this is the solution. My skill in SPIN is not so great. I didn't find it out by myself.
Thank you
Reinhard
Must have been an old version as ersmith mentioned. Versions of my P2 video driver since v0.92 had that issue fixed. Versions are posted here in the first post...
https://forums.parallax.com/discussion/170676/p2-dvi-vga-driver