Hey,
for everyone who is interested in it - here is the
messy source to monoPong - 1k (http://dbfinteractive.com/index.php?topic=2859.msg39150#msg39150).
Most of my knowledge is from Chris - so actually
he owns all credits ;-)
As you can see - packed with Crinkler - there are
still some bytes left. So I would be very interested
to see your enhancements of this code.
//
// monoPong1k
//
// code: benny!weltenkonstrukteur.de
//
// This code is built upon auld's great
// 1k-coding sources/tips. thanks a lot!
// VS2005 modifications
// by benny!weltenkonstrukteur.de
//
#include <windows.h>
#include <GL/gl.h>
#define NULLNULL 0.0000000000f
#define NULLNULLONETRHEE 0.0130000000f
#define NULLNINE 0.8984375000f
#define NULLTWO 0.2001953125f
#define NULLNULLFIVE 0.0500488281f
#define NULLEIGHTSIX 0.8593750000f
#define NULLNULLEIGHT 0.0800781250f
#define NULLFIVE 0.5000000000f
static PIXELFORMATDESCRIPTOR pfd;
static GLfloat batY = NULLNULL;
static GLfloat ballX = NULLNULL;
static GLfloat ballY = NULLNULL;
static GLfloat veloX = NULLNULLONETRHEE;
static GLfloat veloY = NULLNULLONETRHEE;
//
// some math functions
//
static float floatAbs(float f)
{
(int&)f &= ~0x80000000;
return f;
}
//
// drawing stuff
//
static void drawBat(void) {
glBegin(GL_QUADS);
glVertex2f(NULLNULL, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLTWO);
glVertex2f(NULLNULL, NULLTWO);
glEnd();
}
static void render( void ) {
glClear( GL_COLOR_BUFFER_BIT );
glLoadIdentity();
glTranslatef( NULLNINE, -NULLNULLEIGHT + batY, NULLFIVE );
drawBat();
glLoadIdentity();
glTranslatef( -NULLNINE, -NULLNULLEIGHT - batY, NULLNULL );
drawBat();
glLoadIdentity();
glTranslatef( ballX, ballY, NULLNULL );
glBegin(GL_QUADS);
glVertex2f(NULLNULL, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLNULLFIVE);
glVertex2f(NULLNULL, NULLNULLFIVE);
glEnd();
}
void WINAPI WinMainCRTStartup()
{
// auld code
// minimal windows setup code for opengl
pfd.cColorBits = pfd.cDepthBits = 32;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
// "HDC hDC" changed 19. April 2007 by benny!weltenkonstrukteur.de
HDC hDC = GetDC( CreateWindow("edit", 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0) );
SetPixelFormat ( hDC, ChoosePixelFormat ( hDC, &pfd) , &pfd );
wglMakeCurrent ( hDC, wglCreateContext(hDC) );
//ShowCursor(FALSE);
int quit = 0;
DWORD start = GetTickCount();
DWORD cur = 0;
do
{
cur = GetTickCount();
if ( (cur - start ) < 10 ) continue;
start = cur;
ballX+=veloX;
ballY+=veloY;
// check
if ( ballY > NULLNINE ) veloY = -NULLNULLONETRHEE;
if ( ballY < -NULLNINE) veloY = NULLNULLONETRHEE;
float check = floatAbs(batY - ballY);
float check2= floatAbs(-batY - ballY);
if ( ballX > NULLEIGHTSIX && check < NULLTWO ){
veloX = -(0.005f + (check/5));
} else if ( ballX > NULLEIGHTSIX && check > NULLTWO ) {
quit = 1;
}
if ( ballX < -NULLEIGHTSIX && check2 < NULLTWO ){
veloX = 0.005f + (check2/5);
} if ( ballX < -NULLEIGHTSIX && check2 > NULLTWO ) {
quit = 1;
}
if ( GetAsyncKeyState(VK_RIGHT) && batY < NULLNINE ) {
batY += NULLNULLFIVE;
} else if ( GetAsyncKeyState(VK_LEFT) && batY > -NULLNINE) {
batY -= NULLNULLFIVE;
}
render();
SwapBuffers(hDC);
} while ( quit == 0 );
ExitProcess(0);
}
Hmm Benny, try my blog for smaller code...thanks for creds in the code.
Code updated with ExitProcess-function. Thx to
rbraz!
Quote from: taj on January 27, 2008
Hmm Benny, try my blog for smaller code...
thanks for creds in the code.
Your blog bookmarked, mate! It is so cool to
read your sources/tricks!!!
K+ ;D
K++ !! :goodpost:
btw, check our some possible size optimisations ideas/tricks http://dbfinteractive.com/index.php?topic=2859.msg39170#msg39170 (http://dbfinteractive.com/index.php?topic=2859.msg39170#msg39170)
Quote from: va!n on January 27, 2008
hi benny!
Very nice 1k game! I would be proud if it would be my
production *grin*. K++ for the nice work and for the
source! As you may know i dont get work any C/CPP
code (even i want to learn CPP)... i just did a small
view to your source and possible following thing
could optimize your exe size!? (i cant test here, sorry)
... Hope i didnt made any mistake
Thanks a lot for so much input, va!n. I guess there
are many ways it could be optimized ...
Quote from: va!n on January 27, 2008
Your original source:
Static void drawBat(void) {
glBegin(GL_QUADS);
glVertex2f(NULLNULL, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLTWO);
glVertex2f(NULLNULL, NULLTWO);
glEnd();
}
Static void render( void ) {
glClear( GL_COLOR_BUFFER_BIT );
glLoadIdentity();
glTranslatef( NULLNINE, -NULLNULLEIGHT + batY, NULLFIVE );
drawBat();
glLoadIdentity();
glTranslatef( -NULLNINE, -NULLNULLEIGHT - batY, NULLNULL );
drawBat();
glLoadIdentity();
glTranslatef( ballX, ballY, NULLNULL );
glBegin(GL_QUADS);
glVertex2f(NULLNULL, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLNULL);
glVertex2f(NULLNULLFIVE, NULLNULLFIVE);
glVertex2f(NULLNULL, NULLNULLFIVE);
glEnd();
}
Just try out to replace it with this (its possible to optimize
it a bit, to save some more bytes!):
Static void drawObject( fTransX:float, fTransY:float, fTransZ:float, fLeft:float, fBottom:float, fRight:float, fTop:float )
{
glLoadIdentity();
glTranslatef_( fTransX, fTransY, fTransZ, );
glBegin(GL_QUADS);
glVertex2f( fLeft , fBottom );
glVertex2f( fRight, fBottom );
glVertex2f( fRight, fTop );
glVertex2f( fLeft , fTop );
glEnd();
}
Static void render( void ) {
glClear( GL_COLOR_BUFFER_BIT );
// glLoadIdentity();
// glTranslatef( NULLNINE, -NULLNULLEIGHT + batY, NULLFIVE );
// drawBat();
// glLoadIdentity();
// glTranslatef( -NULLNINE, -NULLNULLEIGHT - batY, NULLNULL );
// drawBat();
// glLoadIdentity();
// glTranslatef( ballX, ballY, NULLNULL );
// glBegin(GL_QUADS);
// glVertex2f(NULLNULL, NULLNULL);
// glVertex2f(NULLNULLFIVE, NULLNULL);
// glVertex2f(NULLNULLFIVE, NULLNULLFIVE);
// glVertex2f(NULLNULL, NULLNULLFIVE);
// glEnd();
drawObject( NULLNINE, -NULLNULLEIGHT + batY , NULLNULL, NULLNULL, NULLNULLFIVE, NULLTWO );
drawObject( -NULLNINE, -NULLNULLEIGHT - batY , NULLNULL, NULLNULL, NULLNULLFIVE, NULLTWO );
drawObject( ballX, ballY, NULLNULL, NULLNULL, NULLNULLFIVE, NULLNULLFIVE );
}
I give it a try this evening and check how the exe size will
change and report later.
Quote from: va!n on January 27, 2008
But as i have seen you are using floats, which needs
some extra space in the exe...
...
Yeah. Float values seems to cost bytes. That's why
I tried to define most values with constants referring
to this (http://in4k.untergrund.net/index.php?title=Floating_point_constants) trick.
Quote from: va!n on January 27, 2008
... you could try to use GLUT API which could save
you some bytes by using inbuild 3d objects like:
...
I think glut dependencies costs too much bytes
here.
Anyway, thanks for your ideas. If you got the code setup up
maybe for yourself - I would love to see more changes !!!
@benny:
nothing to thanks for... very sad, i dont manage it to get C/CPP sources compiled here with VC200x Studio... argh... i would relly love to start working with it ;)
However, i tried to optimize my last codesnip a bit (if i didn't made any mistake there, i can't test) to produce hopefully a smaller executeable. just a try
Static void drawObject( fTransX:float, fTransY:float, fTransZ:float, fTop:float ) {
glLoadIdentity();
glTranslatef_( fTransX, fTransY, fTransZ, );
glBegin(GL_QUADS);
glVertex2f( NULLNULL , NULLNULL );
glVertex2f( NULLNULLFIVE, NULLNULL );
glVertex2f( NULLNULLFIVE, fTop );
glVertex2f( NULLNULL , fTop );
glEnd();
}
Static void render( void ) {
glClear( GL_COLOR_BUFFER_BIT );
drawObject( NULLNINE, -NULLNULLEIGHT + batY , NULLFIVE, NULLTWO );
drawObject( -NULLNINE, -NULLNULLEIGHT - batY , NULLNULL, NULLTWO );
drawObject( ballX, ballY, NULLNULL, NULLNULLFIVE );
}
best regards
"Mr.Vain / Secretly!"
[Edited]
Fixed a small mistake i did. sorry.
@mr.va!n:
thanks mate. I will check it out this evening. guess
the last glEnd() command in the render function
should be thrown out ;) .
Would be cool to have enough bytes left to implement
some scoring system!
All you have to remember is one glEnd for every glBegin, and they can't be nested, glBegin followed by glBegin without a glEnd in the middle is an error. I like to call glGetError() every time I call SwapBuffers(), that helps me catch all kinds of stuff-ups.
eg. something like
#include <assert.h>
void flip(void)
{
SwapBuffers(hdc);
assert(glGetError()==GL_NO_ERROR);
}
Jim
@Jim:
ah yes i think you are right... i dont remember this glend rulez... its to long ago when i have used OpenGL ^^
@benny:
so here should be a working version (as i have understand jim hopefully correctly) ^^ btw, you have post
Static void drawObject( fTransX:float, fTransY:float, fTransZ:float, fTop:float ) {
glLoadIdentity();
glTranslatef_( fTransX, fTransY, fTransZ, );
glBegin(GL_QUADS);
glVertex2f( NULLNULL , NULLNULL );
glVertex2f( NULLNULLFIVE, NULLNULL );
glVertex2f( NULLNULLFIVE, fTop );
glVertex2f( NULLNULL , fTop );
}
Static void render( void ) {
glClear( GL_COLOR_BUFFER_BIT );
drawObject( NULLNINE, -NULLNULLEIGHT + batY , NULLFIVE, NULLTWO );
drawObject( -NULLNINE, -NULLNULLEIGHT - batY , NULLNULL, NULLTWO );
drawObject( ballX, ballY, NULLNULL, NULLNULLFIVE );
glEnd();
}
Hmm .. three times glBegin() and just one glEnd() ?
That sounds not very clean - but if it works and saves bytes ::)
@benny:
i am not sure if its correct. atm i am a bit suprised too and cant remember how i did it in the past. (you have to test what version works). if both versions should work, i would like that you use the safe (clean) version instead starting dirty things.
@va!n:
Back home I tested your suggestions.
First of all, the three-times glBegin() and one-time glEnd()
version does not work. Would have been a wonder to
me if it did.
Using correct glBegin/glEnd pairs it works - but the final exe
is 6 bytes bigger now (1020bytes). But hey - it was
worth trying it - sometimes it is nice to see in which way
the crinkler crunches the code best !
Or in other words : Just because the uncompressed size of
code is smaller doesn't automatically mean that the crunched
code is smaller.
okay n thanks for reply... have you tested what happens, if you dont use die DrawObject procedure and insert the code directly? as i told, i will try something too with integers and send you soon... in this minute i am extrem busy, sorry
Np.
I already did certain code rearranging / encapsulation
while programming. But unfortunately I wasnt able to
squeeze more out of it so far :-(
cool little progy benny!
im sure you could get some results using glu primitivs as i think vain suggested, you should'nt need any initilization for them other than linking the lib.
i dont know if they will work out to be any smaller for you but taj uses them in 1k trinity which ive also ported to freebasic and they seem to be rather small to use.
Benny,
I hacked around your code a little. I have to say the game logic is well cool. So is the idea of controlling both bats. Anyway, I got it down to 928 bytes by hook and crook. Note the /QIfist flag to avoid writing your own fabs. Got rid of translates. Got rid of quit variable and test in loop. Re-arranged some tests to reduce the ifs. Used glRect instead of quads. Used a static pfd instead of two lines of code (yes that thing is smaller!).
I think there is still mileage in the game logic to go, but my brain hurts :-)
// New crinkler optimised OpenGL 1k framework.
// /CRINKLER /COMPMODE:SLOW /HASHSIZE:200 /HASHTRIES:50 /ORDERTRIES:6000
// must use /QIfist in Project->Properties->c/C++->command line for "abs" function
// this version is 928 bytes with crinkler 1.0a (haven't tried 1.1 yet).
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#define NULLNULL 0.0000000000f
#define NULLNULLONETRHEE 0.0130000000f
#define NULLNINE 0.8984375000f
#define NULLTWO 0.2001953125f
#define NULLNULLFIVE 0.0500488281f
#define NULLEIGHTSIX 0.8593750000f
#define NULLNULLEIGHT 0.0800781250f
#define NULLFIVE 0.5000000000f
static GLfloat batY, ballX, ballY;
static PIXELFORMATDESCRIPTOR pfd={
0, // Size Of This Pixel Format Descriptor... BAD coding, nothing new, saves 6 bytes
1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0
};
static void drawRect(float x, float y, float s) {
glLoadIdentity();
glRectf(x, y, x+NULLNULLFIVE, y+s);
}
void WINAPI WinMainCRTStartup()
{
DWORD cur;
GLfloat veloX, veloY, check, check2;
veloX=veloY=NULLNULLONETRHEE;
HDC hDC = GetDC( CreateWindow("edit", 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0) );
SetPixelFormat ( hDC, ChoosePixelFormat ( hDC, &pfd) , &pfd );
wglMakeCurrent ( hDC, wglCreateContext(hDC) );
ShowCursor(FALSE);
DWORD start = GetTickCount();
for (;;)
{
cur = GetTickCount();
if ( (cur - start ) < 10 ) continue;
start = cur;
ballX+=veloX;
ballY+=veloY;
if ( ballY > NULLNINE || ballY < -NULLNINE ) veloY = -veloY;
check = abs(batY - ballY);
check2= abs(-batY - ballY);
if ( ballX > NULLEIGHTSIX) if (check<NULLTWO) veloX = -(0.005f + (check/5)); else break;
if ( ballX < -NULLEIGHTSIX) if (check2<NULLTWO) veloX = 0.005f + (check2/5); else break;
if ( GetAsyncKeyState(VK_RIGHT) && batY < NULLNINE ) batY += NULLNULLFIVE;
if ( GetAsyncKeyState(VK_LEFT) && batY > -NULLNINE) batY -= NULLNULLFIVE;
glClear( GL_COLOR_BUFFER_BIT );
drawRect( NULLNINE, -NULLNULLEIGHT + batY, NULLTWO );
drawRect( -NULLNINE, -NULLNULLEIGHT - batY, NULLTWO );
drawRect( ballX, ballY, NULLNULLFIVE );
SwapBuffers(hDC);
}
ExitProcess(0);
}
Taj.
You are unbelieveable taj !!! That's sooooo cool. Thanks a lot.
Great forum, great taj, great day - now I am browsing your code
with open mouth :clap:
Quote from: taj on January 29, 2008
...
// this version is 928 bytes with crinkler 1.0a (haven't tried 1.1 yet).
...
The exe crunched with Crinkler1.1 is 4 bytes bigger (-932bytes).
For everone interested - I attached taj's
version with 928bytes.
@taj:
Again. Thx a lot. Very interesting and helpful to see your
changes and optimazations!!!
@taj:
And of course -> Karma boost !!! :kewl:
Quote from: benny! on January 29, 2008
Quote from: taj on January 29, 2008
...
// this version is 928 bytes with crinkler 1.0a (haven't tried 1.1 yet).
...
The exe crunched with Crinkler1.1 is 4 bytes bigger (-932bytes).
:-) haha. I would check flags though, that sounds like its checking dll safety or something automatically now. Maybe you need to switch that *off*.
Taj
Ooops, I used abs, not fabs. That caused the code to be buggy!
The new one is 899 bytes. I also optimised your game logic a bit better for crinkler (about 10 bytes saved).
Oh yes also was able to remove glLoadIdentity. You might actually be able to add "bloop", "blop" sounds.
// New crinkler optimised OpenGL 1k framework.
// /CRINKLER /COMPMODE:SLOW /HASHSIZE:200 /HASHTRIES:50 /ORDERTRIES:6000
// this version is 899 bytes
#include <windows.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#define NULLNULL 0.0000000000f
#define NULLNULLONETRHEE 0.0130000000f
#define NULLNINE 0.8984375000f
#define NULLTWO 0.2001953125f
#define NULLNULLFIVE 0.0500488281f
#define NULLEIGHTSIX 0.8593750000f
#define NULLNULLEIGHT 0.0800781250f
#define NULLFIVE 0.5000000000f
static GLfloat batY, ballX, ballY;
static PIXELFORMATDESCRIPTOR pfd={
0, // Size Of This Pixel Format Descriptor... BAD coding, nothing new, saves 6 bytes
1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0
};
static void drawRect(float x, float y, float s) {glRectf(x, y, x+NULLNULLFIVE, y+s);}
void WINAPI WinMainCRTStartup()
{
DWORD cur;
GLfloat veloX, veloY, check;
veloX=veloY=NULLNULLONETRHEE;
HDC hDC = GetDC( CreateWindow("edit", 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0) );
SetPixelFormat ( hDC, ChoosePixelFormat ( hDC, &pfd) , &pfd );
wglMakeCurrent ( hDC, wglCreateContext(hDC) );
ShowCursor(FALSE);
DWORD start = GetTickCount();
for (;;)
{
cur = GetTickCount();
if ( (cur - start ) < 10 ) continue;
start = cur;
ballX+=veloX;
ballY+=veloY;
if ( ballY > NULLNINE || ballY < -NULLNINE ) veloY = -veloY;
check = fabs(batY - ballY);
if ( ballX > NULLEIGHTSIX) if (check<NULLTWO) veloX = -(0.005f + (check/5)); else break;
check = abs(-batY - ballY);
if ( ballX < -NULLEIGHTSIX) if (check<NULLTWO) veloX = 0.005f + (check/5); else break;
if ( GetAsyncKeyState(VK_RIGHT) && batY < NULLNINE ) batY += NULLNULLFIVE;
if ( GetAsyncKeyState(VK_LEFT) && batY > -NULLNINE) batY -= NULLNULLFIVE;
glClear( GL_COLOR_BUFFER_BIT );
drawRect( NULLNINE, -NULLNULLEIGHT + batY, NULLTWO );
drawRect( -NULLNINE, -NULLNULLEIGHT - batY, NULLTWO );
drawRect( ballX, ballY, NULLNULLFIVE );
SwapBuffers(hDC);
}
ExitProcess(0);
}
Wow ... amazing. That means that I have tons of
bytes left for more. Good idea about sound. Will think
about.
Kewl!!!
[EDIT]
2nd check calculation should be fabs(), too - eh ?
[/EDIT]
Yes indeed - if you're lucky that will save another 10 bytes.
BTW I tried converting everything to ints except the glRectf function (in which I multiplied the scaled ints by a float to scale them down again). It saved about 20 bytes but I screwed it up somewhere and I cant be bothered to find out where. Still if you are desperate, it can be done. The trick is to use numbers between 0..255 as much as possible (as you are already using 2 byte floats). This ensures there are lots of zeroes in the higher order bytes and the compressor can work better. Also then you can get rid of abs and use & instead- but I didnt try that. It seems to me this can go down as far as about 875 bytes which given that your base (crinkler + open window + loop with swapbuffers + exitprocess) is 617 bytes is really astonishing. Thats about 260 bytes: in C! Next stop : games compendium in 4k.
Benny,
try crinkler 1.1 with these flags:
/CRINKLER /COMPMODE:SLOW /HASHSIZE:200 /HASHTRIES:50 /ORDERTRIES:6000 /UNSAFEIMPORT /TRUNCATEFLOATS:12
(you dont need safe importing dialgue boxes with OGL)
Its now 870 bytes...
Taj
Yeah, taj. Thanks a lot again. Always tried to
avoid /UNSAFEIMPORT option. BUt guess you
are right.
I hope to add some boing sounds this weekend
and see how much space it needs.
Your optimized code really gives me hundreds of
ideas of new concepts to work on !!! :inspired:
Very cool ... that deserves some more K ;)