Evolving as a programmer -- An active journal of my progress
Hello! My name is Tim, I'am a first year computer engineer from sweden.
This year I learnt the basics of programming. That is, learning to crawl(learning programming basics using Python) and learning how to almost walk (learning some of the basics of object-oriented programming using Java).
I just finished the Java course, and found it highly entertaining. I do love programming, and can sit for hours just coding to see what I can do.
Already during the Python course, I felt that I wanted to create some type of game. But at that time, my programming experience was far too inferior to even think of anything graphical. But I still did not give in, and decided that the best way to learn was to try. So I made a very simple and meaningless(story-wise) text-based game that simply relied on inputing pre-determined words to move the game ahead.
This was fine, although looking back, it was ofcourse horribly coded. But we all start somewhere! sadly I no longer have the "game"-file.
However!
2 months after the Python course was finished, the Java course started, opening up a whole new world of impressions, resources and experiences. I loved it.
We learnt the basics of Java and widened our experience with the language every day.
My passion for wanting to make some type of game, any game. Drove me to go far beyond the basic lectures of our Java course.
And I started reading articles, forum posts, watching youtube tutorials etc. trying to learn more about where I should start and HOW I should start.
This brought me to a Java library for making 2d game, named slick2d.
For the last 2 months I have been familiarising myself with the library, learning about how to handle basic inputs, loading sprites, making simple(and without doubt, highly innefective) collission detections etc.
I've started on multiple projects, which naturally has led to me not getting anything done and probably only making my programming experience slow down much more then it has to.
(Note that I'am familiar with 2d game development from younger days, using RPG maker XP. But never did any scripting in it.)
I've been reading quite a hand full of articles here at gamedev.net the past 2-3 weeks, and found them very interesting and educational.
But I still feel that I'am too "wet behind my ears" to truly understand and implement the ideas and concepts from the articles that I've read.
This brings me to the topic.
I read a very interesting article here a few days ago. (Klick here to read it!).
It basicly said that in order to truly learn and evolve during your first steps as a game developer, you need to get one game done a time.
Not bothering making the biggest most innovative and advanced game ever built.
And as you complete game, you step up the difficulty each time.
So I decided, hey! This is exactly what I need to do. (with my own little twist of the whole idea ofcourse).
So 2 days ago, I started making a simple pong game using the slick2d and lwgl library for Java.
It currently containts the following:
- Movable Brick
- Moving Ball (randomly generated at start where it will move first)
- Poor collission detection
- score keeping
- accelerating velocity of ball and brick based on number of times ball hits something (brick or walls)
What it's missing as far as I can imagine right now (Listed in order I believe it should be added):
- Object orientation (Everything is basicly just in one class atm)
- keep variables(data) and methods(behavior) of an object isolated within its own class. (added thanks to warnexus)
- Better input control/implementation
- better and more general collission detection
- enemy ai
- Probably something more that I've forgotten.
As you can see, the list is quite tall and large(in amount of work that has to be done).
My largest concern for the moment is how I should make it better object oriented.
For example, I know that in general I should make something like an entity class and then make a ball class and playerclass (and ai when the time comes) that inherits the entity class. This in it's turn, leads me to reason that the entity class should be abstract.
However, this is a problem for me because I'am not sure how I should make the entity class. Should it contain just a little thing, like an id method and something more, or should it be alot of code in it that handels alot of stuff. And then, if I have a playerclass for example, how would it handle inputs? So many questions...
Thats why I thought that maybe if I made this topic here, I would get help along the way (starting with this Pong game). And as I learn, get help and improve the game. I'll post my progress and how I did it.
This way, I will document my experiences and maybe(hopefully) they will help someone else in a common situation.
That is why, naturally:
All source code will be shared.
I will however, only have the latest "code build" available in this topic, but you can follow my active journal where I will document everything, including sourcecode for each build. ( thanks to ultramailman and j-locke for recomending making an actual journal instead of uploading everything in this topic.)
I hope the people of this community read this topic and help me in my progress of becoming a better programmer and game developer.
Any comments or questions are highly appreciated and I hope we all can help each other!
Now lets get busy!
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PONG - VERSION 1 (THE BEGINNING)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Pictures:
Code:
GameSetup (basicly the window that the game is in)
package engine;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;
public class GameSetup extends StateBasedGame {
private static int width = 720;
private static int height = (width / 12 * 9);
public GameSetup(String name) {
super("Main Game");
}
public static void main(String args[]) {
AppGameContainer app;
try {
app = new AppGameContainer(new GameSetup("Pong"));
app.setDisplayMode(width, height, false);
app.start();
} catch (SlickException ex) {
ex.printStackTrace();
}
}
@Override
public void initStatesList(GameContainer gc) throws SlickException {
this.addState(new PongGame());
}
}
PongGame (The actual game)
package engine;
import java.util.Random;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.KeyListener;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class PongGame extends BasicGameState implements KeyListener {
private boolean gameStarted = false;
private Random randomBool;
private String start = "A self-educational game by Tim Granström\n\n Press SPACE to start game.";
private int width;
private int height;
private float pongY = 150.0f;
private int pongLength = 55;
private float velocityBall = 0.3f;
private float velocityPlayer = 0.3f;
private float ballX = -600.0f;
private float ballY = -150.0f;
private Input input;
private boolean goLeft = true;
private boolean goDown = true;
private int score = 0;
private int bestScore = 0;
private String scoreBoard = "Current Score: ";
private String scoreBestBoard = "Best Score: ";
public void init(GameContainer gc, StateBasedGame sbg)
throws SlickException {
gc.setTargetFrameRate(60);
input = gc.getInput();
width = gc.getWidth();
height = gc.getHeight();
randomBool = new Random();
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g)
throws SlickException {
// draw and color the brick, walls and ball.
g.setColor(Color.white);
g.drawString(scoreBoard+score, 85, 10);
g.drawString(scoreBestBoard+bestScore, 280, 10);
g.drawString(start, (width/2)-150, (height/2)-40);
g.fillRect(5, pongY, 7, pongLength);
g.fillRect(0, 0, width, 8);
g.fillRect(0, height - 8, width, 8);
g.fillRect(width - 8, 0, 8, height);
g.setColor(Color.blue);
g.fillOval(ballX, ballY, 15, 15);
}
public void update(GameContainer gc, StateBasedGame sbg, int delta)
throws SlickException {
if(!gameStarted){
if (input.isKeyDown(Input.KEY_SPACE)) {
goLeft = randomBool.nextBoolean();
goDown = randomBool.nextBoolean();
ballX = 600.0f;
ballY = 150.0f;
gameStarted = true;
}
}
if(gameStarted){
start = "";
// move brick up
if (input.isKeyDown(Input.KEY_UP) || input.isKeyDown(Input.KEY_W)) {
if (pongY > 8) {
pongY -= velocityPlayer * delta;
}
}
// move brick down
if (input.isKeyDown(Input.KEY_DOWN) || input.isKeyDown(Input.KEY_S)) {
if (pongY < height - (8 + pongLength)) {
pongY += velocityPlayer * delta;
}
}
// check if ball collide with brick on left.
if (collideXLeft()) {
goLeft = false;
}
// check if ball collide on right
if (collideXRight(width - (15 + 10))) {
score++;
goLeft = true;
}
if(collideYDown()){
goDown = false;
}
if(collideYUp()){
goDown = true;
}
// if ball is moving to the left
if (goLeft == true) {
ballX -= velocityBall * delta ;
}
// if ball is moving to the right
if (goLeft == false) {
ballX += velocityBall * delta;
}
// if ball is moving up
if (goDown == false){
ballY -= velocityBall * delta;
}
// if ball is moving down
if (goDown == true){
ballY += velocityBall * delta;
}
if(ballX<0){
if(score > bestScore){
bestScore = score;
}
score = 0;
velocityBall = 0.3f;
ballX = 600.0f;
ballY = 150.0f;
gameStarted = false;
}
}
}
private boolean collideXLeft() {
if (pongY - 15 < ballY & ballY < pongY + pongLength+15) {
if (ballX < 13 & ballX > 6) {
velocityBall += 0.0015f;
velocityPlayer += 0.0013f;
return true;
}
else {
return false;
}
}
else {
return false;
}
}
private boolean collideXRight(int widthEdge) {
if (ballX > widthEdge) {
velocityBall += 0.001f;
velocityPlayer += 0.0008f;
return true;
} else {
return false;
}
}
private boolean collideYDown() {
if (ballY > height-8-20) {
velocityBall += 0.001f;
velocityPlayer += 0.0008f;
return true;
} else {
return false;
}
}
private boolean collideYUp() {
if (ballY < 8) {
velocityBall += 0.001f;
velocityPlayer += 0.0008f;
return true;
} else {
return false;
}
}
@Override
public int getID() {
return 0;
}
}
Eclipse Project file:
Thank you for your time!
Cheers.
Tim.