mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Remove conway, pong and snake games.
These games were poorly written and didn't work in graphics mode as they required a vga text mode backend. It's less of a maintenance burden to just remove them as that means the dispd vga text mode support can be deleted.
This commit is contained in:
parent
91a1df02b1
commit
0e577950c0
6 changed files with 3 additions and 764 deletions
|
@ -38,8 +38,7 @@ limited but works on most systems.
|
|||
You can change the display resolution using the `chvideomode` program. However,
|
||||
you need a suitable kernel driver to do the mode setting. The current release
|
||||
only has a simple BGA driver, which works in virtual machines such as Qemu,
|
||||
VirtualBox or Bochs. Note that some programs does not work outside of VGA Text
|
||||
Mode because the dispd library doesn't yet have a VGA->framebuffer converter.
|
||||
VirtualBox or Bochs.
|
||||
|
||||
The BGA driver can support virtually any resolution, but since the interface
|
||||
fails to report which resolutions are appropriate in the current context, I have
|
||||
|
@ -152,7 +151,6 @@ Sortix comes with a number of home-made programs. Here is an overview:
|
|||
* `clear` - clear terminal
|
||||
* `colormake` - colorful version of make (if make is available)
|
||||
* `column` - format lines nicely in columns
|
||||
* `conway` - game of life simulator
|
||||
* `cp` - copy file
|
||||
* `date` - display current time and date
|
||||
* `dirname` - strip last component from file name
|
||||
|
@ -180,14 +178,12 @@ Sortix comes with a number of home-made programs. Here is an overview:
|
|||
* `mkinitrd` - create an initrd
|
||||
* `mv` - move a file
|
||||
* `pager` - display file page by page
|
||||
* `pong` - remake of the classic pong game
|
||||
* `pwd` - print current directory path
|
||||
* `regress` - run system tests
|
||||
* `rm` - remove file
|
||||
* `rmdir` - remove empty directory
|
||||
* `sh` - alias for the shell
|
||||
* `sleep` - delay for a specified amount of time
|
||||
* `snake` - remake of the classic snake game
|
||||
* `sort` - sort lines of text files
|
||||
* `tail` - display end of file
|
||||
* `time` - measure program running time
|
||||
|
@ -278,26 +274,6 @@ Included Games
|
|||
The system comes with a number of small casual games. Note that some games
|
||||
require running in the correct display mode before they will function.
|
||||
|
||||
### Pong ###
|
||||
|
||||
The program `pong` implements a simple pong clone that uses the VGA text mode
|
||||
buffer. Player one controls using `W` and `S`, while player two controls using
|
||||
the arrow keys. This program is only available in VGA mode.
|
||||
|
||||
### Snake ###
|
||||
|
||||
This is a simple snake clone that only works in VGA text mode. You control the
|
||||
snake using the `W`, `S`, `A`, and `D` keys. To run, start the program `snake`.
|
||||
This program is only available in VGA mode.
|
||||
|
||||
### Conway's Game of Life ###
|
||||
|
||||
You can do turing-complete calculations in the classic Game of Life in the VGA
|
||||
text mode buffer. Simply start the program `conway` and use `W`, `A`, `S`, and
|
||||
`D` to navigate the screen. `Space` toggles the current point between live and
|
||||
dead. `C` clears the entire screen, and `R` starts and stops the simulation.
|
||||
This program is only available in VGA mode.
|
||||
|
||||
### Asteroids ###
|
||||
|
||||
Mine for crystals in an asteroid field! Start the `asteroids` program and if you
|
||||
|
@ -481,8 +457,8 @@ likely want to recompile large parts of user-land if you update this library.
|
|||
The dispd library allows processes to communicate with the dispd server that
|
||||
handles window management and graphical output. Currently, there is no such
|
||||
server and the library calls the kernel interface itself. This library allows
|
||||
games such as asteroids and pong to detect the current resolution and request
|
||||
whatever resolution they need to function.
|
||||
games such as asteroids to detect the current resolution and request whatever
|
||||
resolution they need to function.
|
||||
|
||||
cd /src/dispd
|
||||
make
|
||||
|
|
3
games/.gitignore
vendored
3
games/.gitignore
vendored
|
@ -4,7 +4,4 @@
|
|||
*.iso
|
||||
*.so
|
||||
*.a
|
||||
pong
|
||||
conway
|
||||
snake
|
||||
asteroids
|
||||
|
|
|
@ -9,9 +9,6 @@ CXXFLAGS?=$(OPTLEVEL)
|
|||
CXXFLAGS:=$(CXXFLAGS) -Wall -Wextra -fno-exceptions -fno-rtti
|
||||
|
||||
BINARIES:=\
|
||||
pong \
|
||||
conway \
|
||||
snake \
|
||||
asteroids \
|
||||
|
||||
LIBS:=-ldispd
|
||||
|
|
210
games/conway.cpp
210
games/conway.cpp
|
@ -1,210 +0,0 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
conway.cpp
|
||||
Conway's Game of Life.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sortix/vga.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <sys/termmode.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dispd.h>
|
||||
|
||||
const int width = 80;
|
||||
const int height = 25;
|
||||
|
||||
const int rowstride = width + 2;
|
||||
const int buffersize = (height+2) * (width+2);
|
||||
|
||||
uint16_t frame[width*height];
|
||||
|
||||
bool running;
|
||||
int posx;
|
||||
int posy;
|
||||
|
||||
char framea[buffersize];
|
||||
char frameb[buffersize];
|
||||
char* currentframe;
|
||||
char* lastframe;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
// Reset the game data.
|
||||
for ( int i = 0; i < buffersize; i++ ) { framea[i] = 0; frameb[i] = 0; }
|
||||
}
|
||||
|
||||
int Init()
|
||||
{
|
||||
Clear();
|
||||
|
||||
// Initialize variables.
|
||||
currentframe = framea;
|
||||
lastframe = frameb;
|
||||
|
||||
running = false;
|
||||
posy = height / 2 + 1;
|
||||
posx = width / 2 + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Cycle()
|
||||
{
|
||||
// Run a cycle of the game of life.
|
||||
for ( int y = 1; y <= height; y++ )
|
||||
{
|
||||
for ( int x = 1; x <= width; x++ )
|
||||
{
|
||||
int alivearound = 0;
|
||||
int current = lastframe[y * rowstride + x];
|
||||
|
||||
if ( lastframe[(y-1) * rowstride + (x-1)] > 0 ) { alivearound++; }
|
||||
if ( lastframe[(y-1) * rowstride + (x-0)] > 0 ) { alivearound++; }
|
||||
if ( lastframe[(y-1) * rowstride + (x+1)] > 0 ) { alivearound++; }
|
||||
if ( lastframe[(y-0) * rowstride + (x-1)] > 0 ) { alivearound++; }
|
||||
if ( lastframe[(y-0) * rowstride + (x+1)] > 0 ) { alivearound++; }
|
||||
if ( lastframe[(y+1) * rowstride + (x-1)] > 0 ) { alivearound++; }
|
||||
if ( lastframe[(y+1) * rowstride + (x-0)] > 0 ) { alivearound++; }
|
||||
if ( lastframe[(y+1) * rowstride + (x+1)] > 0 ) { alivearound++; }
|
||||
|
||||
currentframe[y * rowstride + x] = ( (current > 0 && (alivearound == 3 || alivearound == 2)) || (current == 0 && alivearound == 3) ) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Swap buffers.
|
||||
char* tmp = lastframe; lastframe = currentframe; currentframe = tmp;
|
||||
}
|
||||
|
||||
void Render()
|
||||
{
|
||||
uint16_t* dest = frame;
|
||||
|
||||
uint16_t set = 'O' | (COLOR8_LIGHT_GREY << 8);
|
||||
uint16_t unset = ' ' | (COLOR8_LIGHT_GREY << 8);
|
||||
|
||||
// Render each cell directly to the VGA framebuffer!
|
||||
for ( int y = 1; y <= height; y++ )
|
||||
{
|
||||
for ( int x = 1; x <= width; x++ )
|
||||
{
|
||||
dest[(y-1) * width + (x-1)] = (lastframe[y * rowstride + x] > 0) ? set : unset;
|
||||
|
||||
// Render the cursor.
|
||||
if ( !running && x == posx && y == posy )
|
||||
{
|
||||
dest[(y-1) * width + (x-1)] |= (COLOR8_RED << 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Read the keyboard input from the user.
|
||||
unsigned termmode = TERMMODE_KBKEY
|
||||
| TERMMODE_UNICODE
|
||||
| TERMMODE_SIGNAL
|
||||
| TERMMODE_NONBLOCK;
|
||||
if ( settermmode(0, termmode) ) { error(1, errno, "settermmode"); }
|
||||
while ( true )
|
||||
{
|
||||
uint32_t codepoint;
|
||||
ssize_t numbytes = read(0, &codepoint, sizeof(codepoint));
|
||||
if ( !numbytes ) { break; }
|
||||
if ( numbytes < 0 ) { break; }
|
||||
int kbkey = KBKEY_DECODE(codepoint);
|
||||
if ( kbkey == KBKEY_R ) { running = !running; }
|
||||
if ( running ) { continue; }
|
||||
if ( kbkey == KBKEY_C ) { Clear(); }
|
||||
if ( kbkey == KBKEY_W ) { if ( posy > 1 ) { posy--; } }
|
||||
if ( kbkey == KBKEY_A ) { if ( posx > 1 ) { posx--; } }
|
||||
if ( kbkey == KBKEY_S ) { if ( posy < height ) { posy++; } }
|
||||
if ( kbkey == KBKEY_D ) { if ( posx < width ) { posx++; } }
|
||||
if ( kbkey == KBKEY_SPACE )
|
||||
{
|
||||
lastframe[posy * rowstride + posx] = 1 - lastframe[posy * rowstride + posx];
|
||||
}
|
||||
}
|
||||
|
||||
// Run a cycle.
|
||||
if ( running ) { Cycle(); }
|
||||
|
||||
Render();
|
||||
}
|
||||
|
||||
int usage(int /*argc*/, char* argv[])
|
||||
{
|
||||
printf("usage: %s [OPTIONS]\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf(" --speed <miliseconds> How many miliseconds between updates\n");
|
||||
printf(" --usage Display this screen\n");
|
||||
printf(" --help Display this screen\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if ( !dispd_initialize(&argc, &argv) )
|
||||
error(1, 0, "couldn't initialize dispd library");
|
||||
|
||||
int sleepms = 50;
|
||||
for ( int i = 1; i < argc; i++ )
|
||||
{
|
||||
if ( strcmp(argv[i], "--help") == 0 ) { return usage(argc, argv); }
|
||||
if ( strcmp(argv[i], "--usage") == 0 ) { return usage(argc, argv); }
|
||||
if ( strcmp(argv[i], "--speed") == 0 && 1 < argc-i )
|
||||
{
|
||||
sleepms = atoi(argv[++i]);
|
||||
}
|
||||
}
|
||||
|
||||
int result = Init();
|
||||
if ( result != 0 ) { return result; }
|
||||
|
||||
struct dispd_session* session = dispd_attach_default_session();
|
||||
if ( !session )
|
||||
error(1, 0, "couldn't attach to dispd default session");
|
||||
if ( !dispd_session_setup_game_vga(session) )
|
||||
error(1, 0, "couldn't setup dispd vga session");
|
||||
struct dispd_window* window = dispd_create_window_game_vga(session);
|
||||
if ( !window )
|
||||
error(1, 0, "couldn't create dispd vga window");
|
||||
|
||||
// Update the game every 50th milisecond.
|
||||
while ( true )
|
||||
{
|
||||
usleep(sleepms * 1000);
|
||||
Update();
|
||||
struct dispd_framebuffer* fb = dispd_begin_render(window);
|
||||
if ( !fb )
|
||||
error(1, 0, "unable to begin rendering dispd window");
|
||||
memcpy(dispd_get_framebuffer_data(fb), frame, sizeof(frame));
|
||||
dispd_finish_render(fb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
287
games/pong.cpp
287
games/pong.cpp
|
@ -1,287 +0,0 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pong.cpp
|
||||
Two-player pong.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sortix/vga.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <sys/termmode.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dispd.h>
|
||||
|
||||
int Init();
|
||||
void Reset();
|
||||
void ClearScreen();
|
||||
void Collision();
|
||||
void Goal(unsigned player);
|
||||
void UpdateUI();
|
||||
void Update();
|
||||
void ReadInput();
|
||||
int main(int argc, char* argv[]);
|
||||
|
||||
const int width = 80;
|
||||
const int height = 25;
|
||||
const int padsize = 5;
|
||||
|
||||
const unsigned goalfreq = 800;
|
||||
const unsigned collisionfreq = 1200;
|
||||
|
||||
uint16_t frame[width*height];
|
||||
|
||||
int ballx;
|
||||
int bally;
|
||||
int oldballx;
|
||||
int oldbally;
|
||||
int ballvelx;
|
||||
int ballvely;
|
||||
int p1y;
|
||||
int p2y;
|
||||
bool p1vup;
|
||||
bool p1vdown;
|
||||
bool p2vup;
|
||||
bool p2vdown;
|
||||
unsigned p1score;
|
||||
unsigned p2score;
|
||||
unsigned time;
|
||||
unsigned soundleft;
|
||||
|
||||
int Init()
|
||||
{
|
||||
Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ClearScreen();
|
||||
|
||||
ballx = width/2;
|
||||
bally = height/2;
|
||||
ballvelx = -1;
|
||||
ballvely = -1;
|
||||
oldballx = ballx - ballvelx;
|
||||
oldbally = bally - ballvely;
|
||||
p1y = (height-padsize) / 5;
|
||||
p2y = (height-padsize) / 5;
|
||||
p1vup = false;
|
||||
p1vdown = false;
|
||||
p2vup = false;
|
||||
p2vdown = false;
|
||||
p1score = 0;
|
||||
p2score = 0;
|
||||
time = 0;
|
||||
soundleft = -1;
|
||||
}
|
||||
|
||||
void ClearScreen()
|
||||
{
|
||||
for ( int y = 0; y < height; y++ )
|
||||
{
|
||||
uint16_t color = COLOR8_BLACK << 8;
|
||||
|
||||
for ( int x = 0; x < width; x++ )
|
||||
{
|
||||
frame[x + y*width] = ' ' | color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Collision()
|
||||
{
|
||||
//System::Sound::SetFrequency(collisionfreq);
|
||||
soundleft = 40;
|
||||
}
|
||||
|
||||
void Goal(unsigned player)
|
||||
{
|
||||
frame[ballx + bally*width] = ' ' | (COLOR8_WHITE << 8);
|
||||
|
||||
int offset = (rand() % 4) - 2;
|
||||
ballx = width/2;
|
||||
bally = height/2 + offset;
|
||||
|
||||
if ( player == 1 )
|
||||
{
|
||||
ballvelx = 1;
|
||||
ballvely = (rand() % 2) * 2 - 1;
|
||||
p1score++;
|
||||
}
|
||||
else if ( player == 2 )
|
||||
{
|
||||
ballvelx = -1;
|
||||
ballvely = (rand() % 2) * 2 - 1;
|
||||
p2score++;
|
||||
}
|
||||
|
||||
if ( ballvely > 0 ) { ballvely /= ballvely; }
|
||||
if ( ballvely < 0 ) { ballvely /= -ballvely; }
|
||||
|
||||
//System::Sound::SetFrequency(goalfreq);
|
||||
soundleft = 50;
|
||||
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
void UpdateUI()
|
||||
{
|
||||
for ( int x = 0; x < width; x++ ) { frame[x] = ' ' | (COLOR8_LIGHT_GREY << 12) | (COLOR8_RED << 8); }
|
||||
|
||||
char num[12];
|
||||
int len;
|
||||
|
||||
len = sprintf(num, "%u", p1score);
|
||||
for ( int i = 0; i < len; i++ ) { frame[i] = ( frame[i] & 0xFF00 ) | num[i]; }
|
||||
|
||||
len = sprintf(num, "%u", p2score);
|
||||
for ( int i = 0; i < len; i++ ) { frame[width - len + i] = ( frame[width - len + i] & 0xFF00 ) | num[i]; }
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
int p1v = 0, p2v = 0;
|
||||
|
||||
if ( p1vup && !p1vdown ) { p1v = -1; } else if ( !p1vup && p1vdown ) { p1v = 1; }
|
||||
if ( p2vup && !p2vdown ) { p2v = -1; } else if ( !p2vup && p2vdown ) { p2v = 1; }
|
||||
|
||||
if ( p1v < 0 && p1y > 1 ) { p1y--; }
|
||||
if ( p1v > 0 && p1y + padsize < height ) { p1y++; }
|
||||
if ( p2v < 0 && p2y > 1 ) { p2y--; }
|
||||
if ( p2v > 0 && p2y + padsize < height ) { p2y++; }
|
||||
|
||||
for ( int y = 1; y < height; y++ )
|
||||
{
|
||||
uint16_t color = ( y < p1y || y >= p1y + padsize ) ? COLOR8_BLACK << 12 : COLOR8_RED << 12; frame[y*width] = ' ' | color;
|
||||
}
|
||||
|
||||
for ( int y = 1; y < height; y++ )
|
||||
{
|
||||
uint16_t color = ( y < p2y || y >= p2y + padsize ) ? COLOR8_BLACK << 12 : COLOR8_BLUE << 12; frame[width-1 + y*width] = ' ' | color;
|
||||
}
|
||||
|
||||
if ( bally + ballvely <= 1 ) { ballvely = 0 - ballvely; Collision(); }
|
||||
if ( bally + ballvely >= height ) { ballvely = 0 - ballvely; Collision(); }
|
||||
|
||||
if ( ballx + ballvelx < 1 ) { if ( bally + ballvely < p1y - 1 || bally + ballvely > p1y + padsize + 1 ) { Goal(2); } else { ballvelx = 0 - ballvelx; Collision(); } }
|
||||
if ( ballx + ballvelx >= width-1 ) { if ( bally + ballvely < p2y - 1 || bally + ballvely > p2y + padsize + 1 ) { Goal(1); } else { ballvelx = 0 - ballvelx; Collision(); } }
|
||||
|
||||
frame[oldballx + oldbally*width] = ' ' | (COLOR8_WHITE << 8);
|
||||
frame[ballx + bally*width] = '.' | (COLOR8_WHITE << 8);
|
||||
oldballx = ballx; oldbally = bally;
|
||||
|
||||
ballx += ballvelx;
|
||||
bally += ballvely;
|
||||
|
||||
frame[ballx + bally*width] = 'o' | (COLOR8_WHITE << 8);
|
||||
}
|
||||
|
||||
void ReadInput()
|
||||
{
|
||||
unsigned termmode = TERMMODE_KBKEY
|
||||
| TERMMODE_UNICODE
|
||||
| TERMMODE_SIGNAL
|
||||
| TERMMODE_NONBLOCK;
|
||||
if ( settermmode(0, termmode) ) { error(1, errno, "settermmode"); }
|
||||
while ( true )
|
||||
{
|
||||
uint32_t codepoint;
|
||||
ssize_t numbytes = read(0, &codepoint, sizeof(codepoint));
|
||||
if ( !numbytes ) { return; }
|
||||
if ( numbytes < 0 ) { return; }
|
||||
int kbkey = KBKEY_DECODE(codepoint);
|
||||
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
|
||||
if ( kbkey == KBKEY_ENTER ) { Reset(); }
|
||||
if ( abskbkey == KBKEY_W ) { p1vup = (0 < kbkey); }
|
||||
if ( abskbkey == KBKEY_S ) { p1vdown = (0 < kbkey); }
|
||||
if ( abskbkey == KBKEY_UP ) { p2vup = (0 < kbkey); }
|
||||
if ( abskbkey == KBKEY_DOWN ) { p2vdown = (0 < kbkey); }
|
||||
}
|
||||
}
|
||||
|
||||
int usage(int /*argc*/, char* argv[])
|
||||
{
|
||||
printf("usage: %s [OPTIONS]\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf(" --speed <miliseconds> How many miliseconds between updates\n");
|
||||
printf(" --usage Display this screen\n");
|
||||
printf(" --help Display this screen\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if ( !dispd_initialize(&argc, &argv) )
|
||||
error(1, 0, "couldn't initialize dispd library");
|
||||
|
||||
int sleepms = 50;
|
||||
for ( int i = 1; i < argc; i++ )
|
||||
{
|
||||
if ( strcmp(argv[i], "--help") == 0 ) { return usage(argc, argv); }
|
||||
if ( strcmp(argv[i], "--usage") == 0 ) { return usage(argc, argv); }
|
||||
if ( strcmp(argv[i], "--speed") == 0 && 1 < argc-i )
|
||||
{
|
||||
sleepms = atoi(argv[++i]);
|
||||
}
|
||||
}
|
||||
|
||||
int result = Init();
|
||||
if ( result != 0 ) { return result; }
|
||||
|
||||
struct dispd_session* session = dispd_attach_default_session();
|
||||
if ( !session )
|
||||
error(1, 0, "couldn't attach to dispd default session");
|
||||
if ( !dispd_session_setup_game_vga(session) )
|
||||
error(1, 0, "couldn't setup dispd vga session");
|
||||
struct dispd_window* window = dispd_create_window_game_vga(session);
|
||||
if ( !window )
|
||||
error(1, 0, "couldn't create dispd vga window");
|
||||
|
||||
while (true)
|
||||
{
|
||||
usleep(sleepms * 1000);
|
||||
ReadInput();
|
||||
Update();
|
||||
UpdateUI();
|
||||
struct dispd_framebuffer* fb = dispd_begin_render(window);
|
||||
if ( !fb )
|
||||
error(1, 0, "unable to begin rendering dispd window");
|
||||
memcpy(dispd_get_framebuffer_data(fb), frame, sizeof(frame));
|
||||
dispd_finish_render(fb);
|
||||
|
||||
if ( /*soundleft < 0*/ false ) { continue; }
|
||||
if ( soundleft <= 50 )
|
||||
{
|
||||
//System::Sound::SetFrequency(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
soundleft -= sleepms;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
234
games/snake.cpp
234
games/snake.cpp
|
@ -1,234 +0,0 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
snake.cpp
|
||||
Single-player snake.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sortix/vga.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <sys/termmode.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dispd.h>
|
||||
|
||||
const int width = 80;
|
||||
const int height = 25;
|
||||
|
||||
const int buffersize = height * width;
|
||||
|
||||
uint16_t frame[width*height];
|
||||
|
||||
int posx;
|
||||
int posy;
|
||||
int velx;
|
||||
int vely;
|
||||
int tailx;
|
||||
int taily;
|
||||
int taillen;
|
||||
int tailmax;
|
||||
int animalx;
|
||||
int animaly;
|
||||
|
||||
char direction[buffersize];
|
||||
|
||||
uint16_t animal = '%' | (COLOR8_RED<<8);
|
||||
uint16_t snake = ' ' | (COLOR8_GREEN<<12);
|
||||
|
||||
const int defaultspeed = 75;
|
||||
const int speedincrease = -5;
|
||||
const int maxspeed = 40;
|
||||
volatile int speed;
|
||||
|
||||
bool tabhack = false;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
// Reset the game data.
|
||||
for ( int i = 0; i < buffersize; i++ ) { frame[i] = ' '; direction[i] = -1; }
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Clear();
|
||||
tailx = posx = width/2;
|
||||
taily = posy = height/2;
|
||||
switch ( rand() % 4 )
|
||||
{
|
||||
case 0: velx = -1; vely = 0; break;
|
||||
case 1: velx = 1; vely = 0; break;
|
||||
case 2: velx = 0; vely = -1; break;
|
||||
case 3: velx = 0; vely = -1; break;
|
||||
}
|
||||
|
||||
animalx = 2 + (rand() % (width-4));
|
||||
animaly = 2 + (rand() % (height-4));
|
||||
|
||||
taillen = 0;
|
||||
tailmax = 3;
|
||||
|
||||
frame[animaly * width + animalx] = animal;
|
||||
|
||||
speed = defaultspeed;
|
||||
}
|
||||
|
||||
int Init()
|
||||
{
|
||||
Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tabhacking = false;
|
||||
|
||||
void Update()
|
||||
{
|
||||
int newvelx = velx;
|
||||
int newvely = vely;
|
||||
|
||||
// Read the keyboard input from the user.
|
||||
unsigned termmode = TERMMODE_KBKEY
|
||||
| TERMMODE_UNICODE
|
||||
| TERMMODE_SIGNAL
|
||||
| TERMMODE_NONBLOCK;
|
||||
if ( settermmode(0, termmode) ) { error(1, errno, "settermmode"); }
|
||||
while ( true )
|
||||
{
|
||||
uint32_t codepoint;
|
||||
ssize_t numbytes = read(0, &codepoint, sizeof(codepoint));
|
||||
if ( !numbytes ) { break; }
|
||||
if ( numbytes < 0 ) { break; }
|
||||
int kbkey = KBKEY_DECODE(codepoint);
|
||||
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
|
||||
if ( tabhack && abskbkey == KBKEY_TAB ) { tabhacking = (0 < kbkey); }
|
||||
if ( kbkey == KBKEY_ENTER ) { Reset(); return; }
|
||||
if ( kbkey == KBKEY_W ) { newvelx = 0; newvely = -1; }
|
||||
if ( kbkey == KBKEY_A ) { newvelx = -1; newvely = 0; }
|
||||
if ( kbkey == KBKEY_S ) { newvelx = 0; newvely = 1; }
|
||||
if ( kbkey == KBKEY_D ) { newvelx = 1; newvely = 0; }
|
||||
}
|
||||
|
||||
if ( tabhack && tabhacking )
|
||||
{
|
||||
if ( animalx == posx && posy < animaly ) { newvelx = 0; newvely = 1; }
|
||||
if ( animalx == posx && posy > animaly ) { newvelx = 0; newvely = -1; }
|
||||
if ( animaly == posy && posx < animalx ) { newvelx = 1; newvely = 0; }
|
||||
if ( animaly == posy && posx > animalx ) { newvelx = -1; newvely = 0; }
|
||||
}
|
||||
|
||||
// Make sure we don't do a 180.
|
||||
if ( !(velx == -1 && newvelx == 1) &&
|
||||
!(velx == 1 && newvelx == -1) &&
|
||||
!(vely == -1 && newvely == 1) &&
|
||||
!(vely == 1 && newvely == -1) )
|
||||
{
|
||||
velx = newvelx; vely = newvely;
|
||||
}
|
||||
|
||||
// Don't collide with the border!
|
||||
if ( posx + velx < 0 || width <= posx + velx ||
|
||||
posy + vely < 0 || height <= posy + vely ) { Reset(); return; }
|
||||
|
||||
int newx = posx + velx;
|
||||
int newy = posy + vely;
|
||||
|
||||
// Move the tail, if needed.
|
||||
if ( taillen == tailmax )
|
||||
{
|
||||
frame[taily * width + tailx] = ' '; taillen--;
|
||||
switch ( direction[taily * width + tailx] )
|
||||
{
|
||||
case 0: tailx--; break;
|
||||
case 1: tailx++; break;
|
||||
case 2: taily--; break;
|
||||
case 3: taily++; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for collision.
|
||||
if ( frame[newy * width + newx] == snake ) { Reset(); return; }
|
||||
|
||||
// Check for food.
|
||||
if ( newx == animalx && newy == animaly )
|
||||
{
|
||||
tailmax++;
|
||||
animalx = 2 + (rand() % (width-4));
|
||||
animaly = 2 + (rand() % (height-4));
|
||||
assert(0 <= animalx && animalx < width);
|
||||
assert(0 <= animaly && animaly < height);
|
||||
if ( maxspeed < speed ) { speed += speedincrease; }
|
||||
}
|
||||
|
||||
frame[animaly * width + animalx] = animal;
|
||||
|
||||
// Remember where we are going.
|
||||
int dir = 0;
|
||||
if ( velx < 0 ) { dir = 0; }
|
||||
if ( velx > 0 ) { dir = 1; }
|
||||
if ( vely < 0 ) { dir = 2; }
|
||||
if ( vely > 0 ) { dir = 3; }
|
||||
direction[posy * width + posx] = dir;
|
||||
|
||||
// Move the head.
|
||||
posx = newx;
|
||||
posy = newy;
|
||||
frame[posy * width + posx] = snake; taillen++;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if ( !dispd_initialize(&argc, &argv) )
|
||||
error(1, 0, "couldn't initialize dispd library");
|
||||
|
||||
for ( int i = 1; i < argc; i++ )
|
||||
{
|
||||
if ( strcmp("--tabhack", argv[i]) == 0 ) { tabhack = true; }
|
||||
}
|
||||
|
||||
int result = Init();
|
||||
if ( result != 0 ) { return result; }
|
||||
|
||||
struct dispd_session* session = dispd_attach_default_session();
|
||||
if ( !session )
|
||||
error(1, 0, "couldn't attach to dispd default session");
|
||||
if ( !dispd_session_setup_game_vga(session) )
|
||||
error(1, 0, "couldn't setup dispd vga session");
|
||||
struct dispd_window* window = dispd_create_window_game_vga(session);
|
||||
if ( !window )
|
||||
error(1, 0, "couldn't create dispd vga window");
|
||||
|
||||
// Update the game every once in a while.
|
||||
while ( true )
|
||||
{
|
||||
usleep(speed * 1000);
|
||||
Update();
|
||||
struct dispd_framebuffer* fb = dispd_begin_render(window);
|
||||
if ( !fb )
|
||||
error(1, 0, "unable to begin rendering dispd window");
|
||||
memcpy(dispd_get_framebuffer_data(fb), frame, sizeof(frame));
|
||||
dispd_finish_render(fb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue