Hello!, I'm new at this forum and relatively new at electronics and microcontrollers.
This time I've not registered here to ask about nothing but to show my experience. Last week i bought an arduino mega and some other utilities like cables, leds and a "J12864" LED display.
It took me a few nights to notice that behind the screen there's a little over-sensitive screw to adjust contrast!. Anyway... heres my first finished first test project!
And here's the crappy code: (maybe it becomes helpful to someone)
#include "U8glib.h"
//Pin Config
U8GLIB_ST7920_128X64 u8g(52, 51, 53, U8G_PIN_NONE); // SPI Com: SCK = en = 52, MOSI = rw = 51, CS = di = 53
//LED - arduino
//-----------------
//blk = ground
//bla = +5v
//psb = ground
//e = 52
//rw = 51
//rs = 53
//vcc = +5v
//gnd = ground
//MegaDrive Controller Pins
// _________
// 5 \ / 1
// 9 \_____/ 6
//joystick - arduino
//--------------------
//pin 7 = 5
//pin 9 = 4
//pin 4 = 3
//pin 3 = 2
//pin 5 = +5v
//pin 8 = ground
uint8_t uiKeySelect = 5; //Output pin for select
uint8_t uiKeyStart = 4; //Input pin for 'start' key
uint8_t uiKeyLeft = 3; //Input pin for 'left' key
uint8_t uiKeyRight = 2; //Input pin for 'right' key
//Key defs
#define KEY_NONE 0
#define KEY_LEFT 1
#define KEY_RIGHT 2
#define KEY_START 3
//Ui Defs
#define UI_WELCOME 0
#define UI_READY 1
#define UI_PLAY 2
#define UI_GAMEOVER 3
//Control variables
uint8_t uiState = UI_WELCOME;
uint8_t uiKeyCode = KEY_NONE;
//InGame variables
uint8_t startBlinkInterval = 0;
uint8_t readyInterval = 0;
int wormRadius = 4;
int wormMaxDelay = 0;
int wormDelay = 0;
int wormPieces;
int wormStartPieces = 6;
float wormDirection = 0.0;
float wormX[255];
float wormY[255];
int pelletX = 0;
int pelletY = 0;
boolean pelletVisible = true;
int pelletBlink = 0;
int pelletBlinkDelay = 2;
String scoreStr = "";
char score[]="000000";
void draw(){
int i;
switch(uiState) {
case UI_WELCOME:
u8g.setFont(u8g_font_fub11);
u8g.drawStr(24, 20, "360 Worm");
startBlinkInterval++;
if (startBlinkInterval <= 40) {
u8g.setFont(u8g_font_04b_03r);
u8g.drawStr(35, 40, "Press start!");
} else if (startBlinkInterval >= 80) {
startBlinkInterval = 0;
}
break;
case UI_READY:
drawPieces();
readyInterval++;
u8g.setFont(u8g_font_04b_03r);
if (readyInterval <= 40) {
u8g.drawStr(47, 40, "Ready");
} else if (readyInterval <= 80 && readyInterval > 40) {
u8g.drawStr(43, 40, "Set");
} else if (readyInterval <= 120 && readyInterval > 80) {
u8g.drawStr(40, 40, "Go!");
} else if (readyInterval > 120) {
readyInterval = 0;
uiState = UI_PLAY;
}
break;
case UI_PLAY:
drawPieces();
break;
case UI_GAMEOVER:
u8g.setColorIndex(1);
u8g.drawBox(0, 0, 128, 64);
u8g.setColorIndex(0);
u8g.setFont(u8g_font_04b_03r);
u8g.drawStr(40, 30, "Game over!");
u8g.drawStr(40, 40, "Score -");
u8g.drawStr(76, 40, score);
u8g.setColorIndex(1);
break;
}
}
void drawPieces(){
int i, x, y;
for(i=0; i<wormPieces; i++) {
x = round(wormX[i]);
y = round(wormY[i]);
u8g.drawCircle(x, y, 1);
u8g.drawPixel(x, y);
}
if (pelletVisible) {
u8g.drawCircle(pelletX, pelletY, 2);
u8g.drawPixel(pelletX, pelletY);
}
}
void controlSetup(void) {
pinMode(uiKeyLeft, INPUT);
digitalWrite(uiKeyLeft, HIGH);
pinMode(uiKeyRight, INPUT);
digitalWrite(uiKeyRight, HIGH);
pinMode(uiKeyStart, INPUT);
digitalWrite(uiKeyStart, HIGH);
pinMode(uiKeySelect, OUTPUT);
digitalWrite(uiKeySelect, HIGH);
}
void controlStep(void) {
uiKeyCode = KEY_NONE;
digitalWrite(uiKeySelect, HIGH);
if (digitalRead(uiKeyLeft) == LOW) {
uiKeyCode = KEY_LEFT;
} else if (digitalRead(uiKeyRight) == LOW) {
uiKeyCode = KEY_RIGHT;
}
digitalWrite(uiKeySelect, LOW);
if (digitalRead(uiKeyStart) == LOW) {
uiKeyCode = KEY_START;
}
}
//Set READY to uiState, prepare initial values.
void startNewGame() {
int i, x, y;
uiState = UI_READY;
wormPieces = wormStartPieces;
wormDirection = 0.0;
x=30; y=20;
for (i=wormPieces-1; i>=0; i--) {
wormX[i] = x;
wormY[i] = y;
x-=wormRadius;
}
resetPelletPosition();
}
//Collision test from two centres and a radius
boolean circularCollision(int x1, int y1, int x2, int y2, int r){
int hyp = sqrt(pow(abs(x2-x1), 2) + pow(abs(y2-y1), 2));
if (hyp <= r) return true;
return false;
}
//This will pick random posible pellet positions until its far away from the worm and the corners
void resetPelletPosition(){
boolean validPosition=false;
int randomX, randomY, i;
do {
randomX = random(4, 124);
randomY = random(4, 60);
validPosition=true;
//Near worm
for(i=0; i<wormPieces; i++) {
if (circularCollision(wormX[i], wormY[i], randomX, randomY, 4)) {
validPosition=false;
break;
}
}
//Near corners
if (circularCollision(0, 0, randomX, randomY, 10) ||
circularCollision(0, 64, randomX, randomY, 10) ||
circularCollision(128, 0, randomX, randomY, 10) ||
circularCollision(128, 64, randomX, randomY, 10)) {
validPosition=false;
}
} while(!validPosition);
pelletX = randomX;
pelletY = randomY;
}
void gameStep(void) {
int i;
//Press start to play game...
if (uiKeyCode == KEY_START && uiState == UI_WELCOME) {
startNewGame();
}
//Game over restart
if (uiKeyCode == KEY_START && uiState == UI_GAMEOVER) {
uiState = UI_WELCOME;
}
//Gameplay
if (uiState == UI_PLAY) {
wormDelay++;
if (wormDelay >= wormMaxDelay) {
//Pellet Blink Animation
pelletBlink++;
if (pelletBlink >= pelletBlinkDelay) {
pelletBlink=0;
if (pelletVisible) {
pelletVisible = false;
} else {
pelletVisible = true;
}
}
//Pellet Collision
if (circularCollision(wormX[wormPieces-1], wormY[wormPieces-1], pelletX, pelletY, 4)) {
wormPieces++;
wormX[wormPieces-1] = wormX[wormPieces-2];
wormY[wormPieces-1] = wormY[wormPieces-2];
resetPelletPosition();
}
//Sides Collision (Game Over)
if (wormX[wormPieces-1] > 128 ||
wormX[wormPieces-1] < 0 ||
wormY[wormPieces-1] > 64 ||
wormY[wormPieces-1] < 0) {
scoreStr = String((wormPieces - wormStartPieces) * 10);
scoreStr.toCharArray(score, 6);
uiState = UI_GAMEOVER;
}
//Worm Collision (Game Over)
for(i=0; i<wormPieces-wormStartPieces; i++) {
if (circularCollision(wormX[wormPieces-1], wormY[wormPieces-1], wormX[i], wormY[i], 2)) {
scoreStr = String((wormPieces - wormStartPieces) * 10);
scoreStr.toCharArray(score, 6);
uiState = UI_GAMEOVER;
break;
}
}
//Worm Movement:
for(i=0; i<wormPieces-1; i++) {
wormX[i] = wormX[i+1];
wormY[i] = wormY[i+1];
}
wormX[wormPieces-1] += cos(wormDirection) * wormRadius;
wormY[wormPieces-1] += sin(wormDirection) * wormRadius;
//Worm direction:
switch (uiKeyCode) {
case KEY_LEFT:
wormDirection -= (PI/7);
break;
case KEY_RIGHT:
wormDirection += (PI/7);
break;
}
if (wormDirection > (2*PI)) {
wormDirection = 0;
} else if (wormDirection < 0) {
wormDirection = (2*PI);
}
//Reset delay
wormDelay = 0;
}
}
}
void setup() {
controlSetup();
//Serial.begin(9600); //Serial log
}
void loop() {
controlStep();
u8g.firstPage();
do {
draw();
} while(u8g.nextPage());
gameStep();
delay(5);
}
Cheers!