1
0
Fork 0
This commit is contained in:
me 2022-11-16 17:36:54 +03:30
parent b83d285241
commit f1e0c492b5
1 changed files with 257 additions and 159 deletions

416
sjump.c
View File

@ -1,22 +1,35 @@
/*
_
| '.
| :
|.' ARRT
_ ___
(_' |
._)QUARE (_:UMP
Authored by abakh <abakh@tuta.io>
To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include <curses.h>
#include <unistd.h>
#include "config.h"
#include "common.h"
#define SAVE_TO_NUM 11
#define SAVE_TO_NUM 10
#define LEN 24
#define HLEN LEN/2
#define WID 80
#define HWID WID/2
#define SIZE 12
#define SHOTS_WHEN_STARTING 10
#define DELAY 50000
#define byte int
#define randint(a,b) ((a)+(rand()%((b+1)-(a))))
#ifdef Plan9
int usleep(long usec) {
@ -31,9 +44,9 @@ int usleep(long usec) {
#endif
// 12 lines of water
// 80 columns
chtype colors[3]={0};
long score=0;
enum {LOSE,WIN};
chtype colors[5]={0};
long score=0,jumps=0;
FILE* scorefile;
chtype background[LEN][WID];
@ -43,20 +56,13 @@ char msg[150]={0};
byte msg_show=0;
bool timed[3];
byte circlex[3];
byte circley[3];
byte squarex[3];
byte squarey[3];
byte loops_left=0;
float shooting_angle=0;
int oy=0;
int ox=0;
float rotation_angle=0;
byte digit_count(int num){
byte ret=0;
do{
++ret;
num/=10;
}while(num);
return ret;
}
int combo=1;
void filled_rect(byte sy,byte sx,byte ey,byte ex){
byte y,x;
for(y=sy;y<ey;++y)
@ -76,18 +82,6 @@ void red_border(void){
}
void fill_aims(){
for(byte i=0;i<26;++i){
aims[i].y= randint(8,HLEN);
aims[i].x= randint(0,HWID);
aims[i].angle=randint(0,628)/100;
aims[i].v=1;
aims[i].sign='A'+i;
aims[i].brake=0;
aims[i].visible=1;
}
}
float center_distance(byte y,byte x){
//y distance is twice accounted for. visual reasons
return sqrt( (y-HLEN)*(y-HLEN)+0.25*(x-HWID)*(x-HWID) );
@ -96,82 +90,24 @@ void star_line(byte y){
for(byte x=1;x<WID-1;++x)
mvaddch(y,x,'.');
}
void make_background(){
float d;
for(byte y=0;y<LEN;++y){
for(byte x=0;x<WID;++x){
d=center_distance(y,x)/(HLEN/4);
if(d<4){
if( ((int)d) %2){
background[y][x]='#';
}
else{
background[y][x]='$'|colors[0];
}
}
else{
background[y][x]=' ';
}
}
}
}
void logo(){
mvaddstr(0,0," _ ");
mvaddstr(1,0,"| '. ");
mvaddstr(2,0,"| : ");
mvaddstr(3,0,"|.' ARRT ");
}
void draw_circle(byte sy,byte sx,char c){
/*chtype c=colors[2];
switch(loops_left){
case -1:
c|='.'
break;
default:
c|='0'+loops_left;
}*/
for(byte y=0;y<5;++y){
for(byte x=0;x<10;++x){
if((y-5)*(y-5)+(x-5)/2*(x-5)/2<25){
mvaddch(sy+y,sx+x,c);
}
}
}
}
void draw_angle(byte sy,byte sx){
float y=sy+5;
float x=sx+5;
for(byte i=0;i<5;++i){
mvaddch((byte)y,(byte)x,'#'|A_BOLD);
y+=sin(shooting_angle);
x+=cos(shooting_angle)/2;
}
}
void draw(){
for(byte i=0;i<3;++i){
draw_circle(circley[i],circlex[i],'.');
}
draw_angle(circley[0],circlex[0]);
logo();
if(msg_show){
--msg_show;
mvaddstr(LEN-1,0,msg);
}
mvprintw(0,0," _ ___ ");
mvprintw(1,0,"(_' | Score: %d",score);
mvprintw(2,0,"._)QUARE (_:UMP Combo: %d",combo);
addch('\n');
}
byte save_score(void){
return fallback_to_home("circlejump_scores",score,SAVE_TO_NUM);
return fallback_to_home("sjump_scores",score,SAVE_TO_NUM);
}
void show_scores(byte playerrank){
filled_rect(0,0,LEN,WID);
red_border();
erase();
logo(0,0);
if(playerrank==FOPEN_FAIL){
mvaddstr(1,0,"Could not open score file.");
mvprintw(2,0,"However, your score is %ld.",score);
mvaddstr(3,0,"Could not open score file");
printw("\nHowever, your score is %ld.",score);
refresh();
return;
}
@ -179,49 +115,203 @@ void show_scores(byte playerrank){
char formername[60]={0};
long formerscore=0;
rewind(score_file);
fscanf(score_file,"%*s : %*d");
if ( fscanf(score_file,"%s : %ld",formername,&formerscore)==2 && formerscore>0){
byte a = (LEN-9)/2;
star_line(1);
star_line(LEN-2);
mvaddstr(1,WID/2-8,"CONGRATULATIONS!!");
mvprintw(a+1,HWID-10," _____ You bet the");
mvprintw(a+2,HWID-10," .' | previous");
mvprintw(a+3,HWID-10," .' | record");
mvprintw(a+4,HWID-10," | .| | of");
mvprintw(a+5,HWID-10," |.' | |%11ld",formerscore);
mvprintw(a+6,HWID-10," | | held by");
mvprintw(a+7,HWID-10," ___| |___%7s!",formername);
mvprintw(a+8,HWID-10," | |");
mvprintw(a+9,HWID-10," |____________|");
mvprintw(LEN-3,HWID-11,"Press a key to continue");
refresh();
do{
input=getch();
}while((input==KEY_UP||input=='w') || (input==KEY_DOWN||input=='s'));
filled_rect(0,0,LEN,WID);
red_border();
fscanf(score_file,"%*s : %*d\n");
move(4,0);
byte b=0;
if ( fscanf(score_file,"%s : %ld\n",formername,&formerscore)==2){
halfdelay(1);
printw("*****CONGRATULATIONS!****\n");
printw(" You beat the\n");
printw(" previous\n");
printw(" record\n");
printw(" of\n");
printw(" %14ld\n",formerscore);
printw(" held by\n");
printw(" %11s\n",formername);
printw(" \n");
printw(" \n");
printw("*************************\n");
printw("Press a key to proceed:");
Effect:
move(4,0);
mvprintw(4,0, " _____ ");
mvprintw(5,0, " .' |");
mvprintw(6,0, " .' |");
mvprintw(7,0, " | .| |");
mvprintw(8,0, " |.' | |");
mvprintw(9,0, " | |");
mvprintw(10,0," ___| |___");
mvprintw(11,0," | |");
mvprintw(12,0," |____________|");
b=(b+1)%6;
if(getch()==ERR)
goto Effect;
nocbreak();
cbreak();
erase();
logo(0,0);
}
}
//scorefile is still open with w+
move(4,0);
char pname[60] = {0};
long pscore=0;
byte rank=0;
rewind(score_file);
mvaddstr(1,WID/2-4,"HIGH SCORES");
attron(colors[3]);
rewind(score_file);
printw(">*>*>Top %d<*<*<\n",SAVE_TO_NUM);
while( rank<SAVE_TO_NUM && fscanf(score_file,"%s : %ld\n",pname,&pscore) == 2){
star_line(2+2*rank);
move(2+2*rank,1);
if(rank == playerrank)
printw(">>>");
printw("%s",pname);
mvprintw(2+2*rank,WID-1-digit_count(pscore),"%d",pscore);
printw("%d) %s : %ld\n",rank+1,pname,pscore);
++rank;
}
addch('\n');
refresh();
}
void draw_square(byte sy,byte sx){
for(byte y=0;y<SIZE;++y){
mvaddch(sy+y,sx,ACS_VLINE);
mvaddch(sy+y,sx+SIZE*2,ACS_VLINE);
}
for(byte x=0;x<SIZE*2;++x){
mvaddch(sy,sx+x,ACS_HLINE);
mvaddch(sy+SIZE,sx+x,ACS_HLINE);
}
mvaddch(sy,sx,ACS_ULCORNER);
mvaddch(sy+SIZE,sx+SIZE*2,ACS_LRCORNER);
mvaddch(sy+SIZE,sx,ACS_LLCORNER);
mvaddch(sy,sx+SIZE*2,ACS_URCORNER);
}
void move_o(){
if(ox==0){
if(oy==0){
ox++;
}
else{
oy--;
}
}
else if(ox==SIZE*2){
if(oy==SIZE){
ox--;
combo=1;
}
else{
oy++;
}
}
else if(oy==SIZE){
if(ox==0){
oy--;
}
else{
ox--;
}
}
else if(oy==0){
if(ox==SIZE*2){
oy++;
}
else{
ox++;
}
}
//---->---
//| |
//^ V
//| |
//----<---
}
void draw_angle(byte sy,byte sx){
int y=sy+oy;
int x=sx+ox;
attron(colors[0]);
mvaddch(y,x,'O');
attroff(colors[0]);
}
void draw(int sy,int sx){
for(byte i=0;i<3;++i){
draw_square(sy+squarey[i],sx+squarex[i]);
}
logo();
}
byte shooting_scene(){
float dy=(oy-(SIZE/2))/(float)SIZE;
float dx=(ox-(SIZE))/(float)(SIZE*2);
dy/=2;//it was too hard :(
float y=squarey[0]+oy;
float x=squarex[0]+ox;
float offsetx=0;
float offsety=0;
float doffsety=0;
float doffsetx=-dx*2;
byte reached_o=0;
while(1){
erase();
draw(offsety,offsetx);
if(round(x)<=-round(offsetx)+1){//slow the animation
reached_o=1;
}
attron(colors[0]);
mvaddch(round(y)+round(offsety),round(x)+round(offsetx),'O');
attroff(colors[0]);
for(byte i=0;i<1;i++){
y+=dy;
x+=dx;
offsety+=doffsety;
if(reached_o){
offsetx=-x;
}
else{
offsetx+=doffsetx;
}
if( y>=LEN-1 || y<=1|| x> squarex[1]+SIZE*3 || x<-SIZE){
combo=1;
return LOSE;
}
if(y>=squarey[1] && x>=squarex[1] && y<=squarey[1]+SIZE && round(x)<=squarex[1]+SIZE*2){
if(round(y)==squarey[1] || round(y)==squarey[1]+SIZE){
score+=combo*101;
}
else{
score+=combo;
}
combo++;
jumps++;
oy=round(y)-squarey[1];
ox=round(x)-squarex[1];
for(byte i=0;i<3;++i){
squarey[i]+=offsety;
squarex[i]+=offsetx;
}
squarey[0]=squarey[1];
squarex[0]=squarex[1];
squarey[1]=squarey[2];
squarex[1]=squarex[2];
squarex[2]=squarex[1]+WID-SIZE;
squarey[2]=5+ (rand()%(LEN-(5+SIZE)));
//since square 0 always ends up at the center after the animation,
//square 2 should be choosen in a way that it would still remain
//in the screen after the animation in which it becomes square 1.
return WIN;
}
}
refresh();
if(reached_o){
usleep(DELAY/6);
}
else{
usleep(DELAY/3);
}
}
}
void help(void){
nocbreak();
cbreak();
@ -229,9 +319,7 @@ void help(void){
filled_rect(0,0,LEN,WID);
red_border();
mvprintw(1,HWID-4,"GAME PLAY");
mvprintw(3,1,"If you hit a letter on keyboard, the letter on the");
mvprintw(4,1,"screen will soon stop. You have to aim for the");
mvprintw(5,1,"center of the target using the moving letters.");
mvprintw(3,1,"Jump from square to square.");
attroff(colors[3]);
refresh();
getch();
@ -251,53 +339,63 @@ int main(void){
srand(time(NULL)%UINT_MAX);
if(has_colors()){
start_color();
init_pair(1,COLOR_RED,COLOR_BLACK);
init_pair(2,COLOR_YELLOW,COLOR_BLACK);
init_pair(3,COLOR_GREEN,COLOR_BLACK);
for(byte b=0;b<3;++b)
use_default_colors();
init_pair(1,COLOR_RED,-1);
init_pair(2,COLOR_YELLOW,-1);
init_pair(3,COLOR_GREEN,-1);
init_pair(4,COLOR_MAGENTA,-1);
init_pair(5,COLOR_BLUE,-1);
for(byte b=0;b<5;++b)
colors[b]=COLOR_PAIR(b+1);
}
make_background();
Start:
oy=ox=0;
squarey[0]=5;
squarex[0]=0;
squarey[1]=5;
squarex[1]=squarex[0]+WID-SIZE;
squarey[2]=5;
squarex[2]=squarex[1]+WID-SIZE;
erase();
halfdelay(1);
nodelay(stdscr,1);
curs_set(0);
score=0;
msg_show=0;
aims_to_stop=shots=SHOTS_WHEN_STARTING;
fill_aims();
while(1){
draw();
erase();
draw(0,0);
draw_angle(squarey[0],squarex[0]);
refresh();
input=getch();
move_o();
if(input=='?' || input==KEY_F(1))
help();
if(input=='Q'){
strcpy(msg,"Ctrl-C to quit.");
msg_show=50;
}
if(input!=ERR){
usleep(100000);
flushinp();
}
if(!aims_to_stop){
if(input=='q'){
break;
}
for(int i=0;i<26;++i){
move_aim(aims+i);
if(input=='\n'||input==KEY_ENTER){
if(shooting_scene()==LOSE){
break;
}
}
usleep(DELAY);
if(input!=ERR){
flushinp();
}
}
nodelay(stdscr,0);
flushinp();
nocbreak();
cbreak();
curs_set(1);
end_scene();
mvprintw(LEN,0,"Press a key to see the high scores:");
refresh();
getch();
show_scores(save_score());
attron(colors[0]|A_STANDOUT);
mvprintw(LEN-1,HWID-11,"Wanna play again? (y/n)");
attroff(colors[0]|A_STANDOUT);
printw("\n\nWanna play again? (y/n)");
do{
input=getch();
}while((input==KEY_UP||input=='w') || (input==KEY_DOWN||input=='s'));