Java 4k game Programming Contest

Você anda procurando algo interessante pra fazer no seu tempo livre? ta entediado no trabalho? que tal se inscrever nesse concurso que premia os melhores jogos feitos em Java com apenas 4k de tamanho (4096 bytes).

Tão util quanto um copo de café vazio na mesa, os premios tambem sao “muito atrativos” (entre aspas mesmo :wink: )

Tirando isso, é legal pra fazer algo de interessante enquanto o youtube fica fora do ar.

http://javaunlimited.net/contests/java4k.php

Legal, isso me lembrou os concursos de Jogos em BASIC do MSX em uma linha… 256 bytes :smiley:

Com certeza, lembrei do famoso asm2k particiei diversas vezes infelizmente não ganhei nenhum, mas valeu a pena pela experiencia, bom para quem tinha 16 anos morando fora e nao tinha muito oque fazer era ótimo.

Alguém pode postar algum material que sirva como base para desenvolvimento de jogos em Java !

Se possível jogos pequenos, como exigidos ai …

Obrigado.

Pow, essa eu quero ver hein… 4k :slight_smile:

show de bola.

O que quer dizer:

nas regras do concurso?

[quote=lavh]O que quer dizer:

nas regras do concurso?[/quote]

'e uma api para compressao de jar que geralmente 'e usada pra voce nao gastar banda atoa quando ta passando os dados. se eu nao me encano vc pode ate dar deploy no arquivo comprimido.

http://java.sun.com/j2se/1.5.0/docs/guide/deployment/deployment-guide/pack200.html

http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/pack200.html

e o pior (na verdade melhor) é que o pessoal faz jogo bom viu… sempre tem um pessoal bem criativo participando.

Só pode jogos em modo texto?

Boa pergunta… eu não tenho acesso ao site pra ver as regras, alguém poderia colar aqui ou mandar via mp?

Normalmente esse tipo de restrição não acontece, ainda mais com jogos, mas vamos ver né…

Parece que pode usar o Java 2D, visto que o mesmo faz parte do core do Java.

Quais são os prêmios? (o site aqui é barrado, não tem como eu entrar)

[quote=Contest]Contest Prizes

* 6 months free playtime of Wurm Online( http://wurmonline.com/ ), courtesy of Mojang Specifications ( http://mojang.com/ )!

* Top 5 entries score a free copy of Tribal Trouble ( http://tribaltrouble.com/ ), courtesy of Oddlabs ( http://oddlabs.com/ )!

[/quote]

O jogo campeão do ano passado era estilo lemmings, muito legal e viciante. Adoro esse tipo de competição.

e ai pessoal…

quem ja fez o seu game heim?

eu fiz um aqui so pra brincar, mas ta dificil de deixar com 4k…

[code]
package com.psinfo.pspong;

import java.awt.;
import java.awt.event.
;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

public class PSPong extends JFrame implements ActionListener, KeyListener, ItemListener {

private static final long serialVersionUID = 1l;
private JPanel stadiun, playOne, playTwo, ball;
private JComboBox jcbSpeed;
private JLabel result;
private Timer timer = new Timer( 30, this );
private boolean left, rigth, up, down;
private List&lt Integer &gt speeds = new ArrayList&lt Integer &gt();
private final int PLAYERUP = 0, PLAYERDOWN = 1, ONEPLAYER = 1, TWOPLAYER = 2;
private int sizePlayers = ONEPLAYER, SCOREPLAYONE = 0, SCOREPLAYTWO = 0;

public PSPong() {
	super( "PSPong" );
	setSize( 398, 357 );
	setResizable( false );
	setLocationRelativeTo( this );
	setDefaultCloseOperation( DISPOSE_ON_CLOSE );
	initComponents();
	addKeyListener( this );
	setVisible( true );
	stadiun.requestFocus();
}

private void initComponents() {
	speeds.add( 2 );
	speeds.add( 4 );
	speeds.add( 8 );
	speeds.add( 12 );
	speeds.add( 20 );
	JMenuBar bar = new JMenuBar();
	setJMenuBar( bar );
	JMenu mFile = new JMenu( "File" ), mHelp = new JMenu( "Help" );
	JRadioButtonMenuItem rbmiOnePlayer = new JRadioButtonMenuItem( "One player", true ), rbmiTwoPlayer = new JRadioButtonMenuItem( "Two player" );
	JMenuItem miExit = new JMenuItem( "exit" ), miHelp = new JMenuItem( "help" ), miAbout = new JMenuItem( "about" );
	bar.add( mFile );
	mFile.add( rbmiOnePlayer );
	mFile.add( rbmiTwoPlayer );
	mFile.addSeparator();
	mFile.add( miExit );
	bar.add( mHelp );
	mHelp.add( miHelp );
	mHelp.addSeparator();
	mHelp.add( miAbout );
	rbmiOnePlayer.addActionListener( this );
	rbmiTwoPlayer.addActionListener( this );
	miExit.addActionListener( this );
	miHelp.addActionListener( this );
	miAbout.addActionListener( this );
	ButtonGroup bg = new ButtonGroup();
	bg.add( rbmiOnePlayer );
	bg.add( rbmiTwoPlayer );
	getContentPane().setLayout( new BorderLayout() );
	JPanel jp = new JPanel();
	jp.setLayout( new BorderLayout() );
	jp.setPreferredSize( new Dimension( 390, 20 ) );
	result = new JLabel( " play two    X    play one" );
	jp.add( result, BorderLayout.WEST );
	jp.add( new JLabel( "speed : ", SwingConstants.RIGHT ), BorderLayout.CENTER );
	jcbSpeed = new JComboBox( new String[] { "1", "2", "3", "4", "5" } );
	jcbSpeed.setPreferredSize( new Dimension( 50, 20 ) );
	jp.add( jcbSpeed, BorderLayout.EAST );
	jcbSpeed.setSelectedIndex( 2 );
	jcbSpeed.addItemListener( this );
	getContentPane().add( jp, BorderLayout.NORTH );
	stadiun = new JPanel();
	stadiun.setLayout( null );
	stadiun.setSize( 390, 280 );
	stadiun.setPreferredSize( new Dimension( 390, 280 ) );
	stadiun.setBackground( new Color( 100, 150, 100 ) );
	playOne = new JPanel();
	playOne.setLayout( null );
	playOne.setSize( 10, 40 );
	playOne.setBackground( Color.ORANGE );
	playTwo = new JPanel();
	playTwo.setLayout( null );
	playTwo.setSize( 10, 40 );
	playTwo.setBackground( Color.ORANGE );
	ball = new JPanel();
	ball.setLayout( null );
	ball.setSize( 10, 10 );
	getContentPane().add( stadiun, BorderLayout.CENTER );
	ball.setLocation( ( stadiun.getPreferredSize().width / 2 ) - 5, ( stadiun.getPreferredSize().height / 2 ) - 5 );
	stadiun.add( ball );
	playTwo.setLocation( 5, ( stadiun.getPreferredSize().height / 2 ) - 20 );
	stadiun.add( playTwo );
	playOne.setLocation( 375, ( stadiun.getPreferredSize().height / 2 ) - 20 );
	stadiun.add( playOne );
	stadiun.addKeyListener( this );
	ball.addKeyListener( this );
	playOne.addKeyListener( this );
	playTwo.addKeyListener( this );
}

private void newGame() {
	int vert = (int) Math.random() * 21, hor = (int) Math.random() * 21;
	if ( vert % 2 == 0 ) {
		rigth = true;
		left = false;
	}
	else {
		left = true;
		rigth = false;
	}
	if ( hor % 2 == 0 ) {
		up = true;
		down = false;
	}
	else {
		down = true;
		up = false;
	}
	SCOREPLAYONE = 0;
	SCOREPLAYTWO = 0;
	viewResult();
	if ( timer.isRunning() ) {
		timer.stop();
	}
	timer.start();
}

private void pauseGame() {
	if ( timer.isRunning() ) {
		timer.stop();
	}
	else {
		timer.start();
	}
}

private void stopGame() {
	SCOREPLAYONE = 0;
	SCOREPLAYTWO = 0;
	if ( timer.isRunning() ) {
		timer.stop();
	}
	ball.setLocation( ( stadiun.getPreferredSize().width / 2 ) - 5, ( stadiun.getPreferredSize().height / 2 ) - 5 );
	playTwo.setLocation( 5, ( stadiun.getPreferredSize().height / 2 ) - 20 );
	playOne.setLocation( 375, ( stadiun.getPreferredSize().height / 2 ) - 20 );
}

private void movePlayerOne( int a ) {
	int x = playOne.getX(), y = playOne.getY(), speed = speeds.get( jcbSpeed.getSelectedIndex() &gt -1 ? jcbSpeed.getSelectedIndex() : 2 ) * 2;
	if ( a == PLAYERUP ) {
		if ( y &gt 0 ) {
			y -= speed;
		}
	}
	else if ( a == PLAYERDOWN ) {
		if ( y &lt 240 ) {
			y += speed;
		}
	}
	playOne.setLocation( x, y );
	playOne.repaint();
	stadiun.repaint();
}

private void movePlayerTwo( int a ) {
	int x = playTwo.getX(), y = playTwo.getY(), speed = speeds.get( jcbSpeed.getSelectedIndex() &gt -1 ? jcbSpeed.getSelectedIndex() : 2 );
	if ( sizePlayers == TWOPLAYER ) {
		speed = speed * 2;
	}
	else {
		speed++;
	}
	if ( a == PLAYERUP ) {
		if ( y &gt 0 ) {
			y -= speed;
		}
	}
	else if ( a == PLAYERDOWN ) {
		if ( y &lt 240 ) {
			y += speed;
		}
	}
	playTwo.setLocation( x, y );
	playTwo.repaint();
	stadiun.repaint();
}

private void moveBall() {
	int x = ball.getX(), y = ball.getY(), speed = speeds.get( jcbSpeed.getSelectedIndex() &gt -1 ? jcbSpeed.getSelectedIndex() : 2 );
	if ( left ) {
		if ( x &lt 15 ) {
			if ( ( y &lt ( playTwo.getY() - 10 ) ) || ( y &gt ( playTwo.getY() + 40 ) ) ) {
				SCOREPLAYONE++;
				viewResult();
			}
			left = false;
			rigth = true;
		}
		else {
			x -= speed;
		}
	}
	else if ( rigth ) {
		if ( x &gt 365 ) {
			if ( ( y &lt ( playOne.getY() - 10 ) ) || ( y &gt ( playOne.getY() + 40 ) ) ) {
				SCOREPLAYTWO++;
				viewResult();
			}
			left = true;
			rigth = false;
		}
		else {
			x += speed;
		}
	}
	if ( up ) {
		if ( y &lt 0 ) {
			up = false;
			down = true;
			y = 0;
		}
		else {
			y -= speed;
		}
	}
	else if ( down ) {
		if ( y &gt 260 ) {
			down = false;
			up = true;
			y = 260;
		}
		else {
			y += speed;
		}
	}
	if ( sizePlayers == ONEPLAYER ) {
		if ( up ) {
			movePlayerTwo( PLAYERUP );
		}
		else if ( down ) {
			movePlayerTwo( PLAYERDOWN );
		}
	}
	ball.setLocation( x, y );
	ball.repaint();
	stadiun.repaint();
}

private void viewResult() {
	result.setText( " play two " + SCOREPLAYTWO + "   X   " + SCOREPLAYONE + " play one" );
	if ( SCOREPLAYONE == 10 ) {
		stopGame();
		JOptionPane.showMessageDialog( this, "PLAYER ONE WINNER !!!" );
	}
	else if ( SCOREPLAYTWO == 10 ) {
		stopGame();
		JOptionPane.showMessageDialog( this, "PLAYER TWO WINNER !!!" );
	}
	else {
		pauseGame();
		ball.setLocation( ( stadiun.getPreferredSize().width / 2 ) - 5, ( stadiun.getPreferredSize().height / 2 ) - 5 );
		playTwo.setLocation( 5, ( stadiun.getPreferredSize().height / 2 ) - 20 );
		playOne.setLocation( 375, ( stadiun.getPreferredSize().height / 2 ) - 20 );
	}
}

public void actionPerformed( ActionEvent e ) {

	if ( "exit".equals( e.getActionCommand() ) ) {
		System.exit( 0 );
	}
	else if ( "help".equals( e.getActionCommand() ) ) {
		JOptionPane.showMessageDialog( this, "Player One\nmove up    -&gt key up\nmove down  -&gt key down\n\nPlayer Two\nmove up    -&gt key Q\nmove down  -&gt key A\n\nnew game   -&gt key N\npause/play -&gt key P\nstop       -&gt key X\n\n", "help", JOptionPane.QUESTION_MESSAGE );
	}
	else if ( "about".equals( e.getActionCommand() ) ) {
		JOptionPane.showMessageDialog( this, "PSPong\n\nby PS Info - pregospan\n(c) pregospan 2000 - 2007\n\npregospan@gmail.com", "aboult", JOptionPane.PLAIN_MESSAGE );
	}
	else if ( "One player".equals( e.getActionCommand() ) ) {
		sizePlayers = ONEPLAYER;
	}
	else if ( "Two player".equals( e.getActionCommand() ) ) {
		sizePlayers = TWOPLAYER;
	}
	else if ( e.getSource() == timer ) {
		moveBall();
	}
}

public void keyPressed( KeyEvent e ) {
	if ( e.getKeyCode() == KeyEvent.VK_UP ) {
		movePlayerOne( PLAYERUP );
	}
	else if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
		movePlayerOne( PLAYERDOWN );
	}
	else if ( e.getKeyCode() == KeyEvent.VK_Q ) {
		if ( sizePlayers == TWOPLAYER ) {
			movePlayerTwo( PLAYERUP );
		}
	}
	else if ( e.getKeyCode() == KeyEvent.VK_A ) {
		if ( sizePlayers == TWOPLAYER ) {
			movePlayerTwo( PLAYERDOWN );
		}
	}
	else if ( e.getKeyCode() == KeyEvent.VK_N ) {
		newGame();
	}
	else if ( e.getKeyCode() == KeyEvent.VK_P ) {
		pauseGame();
	}
	else if ( e.getKeyCode() == KeyEvent.VK_X ) {
		stopGame();
	}
}

public void itemStateChanged( ItemEvent e ) {
	if ( e.getSource() == jcbSpeed ) {
		stadiun.requestFocus();
	}
}

public void keyReleased( KeyEvent e ) { }

public void keyTyped( KeyEvent e ) { }

public static void main( String[] args ) {

	new PSPong();
}

}[/code]

sera que alguem consegue deixar com 4k esse ai…

pregospan,

Eu tava pensando em criar um em swing e ou Java2D, mas acho que fica pior para manter o código em 4k, mas quem fizer, será uma arte.

[quote=pregospan]e ai pessoal…

quem ja fez o seu game heim?

eu fiz um aqui so pra brincar, mas ta dificil de deixar com 4k…

sera que alguem consegue deixar com 4k esse ai…[/quote]

Olá,

Removi o package (ou seja, deixei no package default), compilei com eclipse sem as informações de debug e compressei com (Send to - compressed folder) do windows e ficou 3 833 bytes. Ou seja, dentro do limite.

O cara que escreveu o jogo que ganhou no ano passado escreveu isto:

...
 * To get this game to compress to under 4kb, I used proguard to obfuscate, and BJWFlate to pack.
 * The source code is kinda messy because of the nature of the project, but I've added plenty of comments.
...

Então acho que esse é o caminho. Esqueça da OO. Um ofuscador ajuda renomer os nomes dos campos e métodos e provavelmente até fazer outras coisas que otimizam o tamanho.

Algumas outras coisas que podem ajudar:
*Em vez de utilizar campos, utilize variáveis locais
*Minimize o número de métodos no seu classe (aquele jogo que ganhou tem um método para eventos da interface gráfica, o método main e só).
*Reuse (abuse, até) as variáveis locais, pois as instruções de bytecode que acessam os primeiro 4 variáveis locais são 1 byte, para o quinto variavel local e o resto as instruções são 2 bytes.
*Também seria bom definir os variaveis locais na ordem baseada na frequencia de uso, do jeito que os que são mais utilizados são definidos primeiro, justamente pela razão citada acima. (Não sei se o ofuscador faz isto ou não.)

[]s,
Sami

Para os eventos de mouse, teclado, etc, a abordagem do jogo Miners4k parece eficiente em termos de tamanho: Sobre-escrever o método processEvent(AWTEvent) da classe java.awt.Window e faça um switch-case para tratar os vários eventos:

    public void processEvent(AWTEvent e)
    {
        switch (e.getID())
        {
            case WindowEvent.WINDOW_CLOSING:
                ...
                break;
            case MouseEvent.MOUSE_RELEASED:
                ...
                break;
            case MouseEvent.MOUSE_PRESSED:
                ...
                break;
            case KeyEvent.KEY_PRESSED:
                ....
                break;
        }
    }

[]s,
Sami