First Foray Into ChatGPT Game Writing: ChatGPT Chomp
Ok, I’ve seen hundreds of posts on ChatGPT Already and it’s ability to write magical code. Is it going to eventually replace us developers? Who knows! All I can say that as almost everyone has at this point, it’s pretty impressive.
I’ve already used it for a number of things, and I wanted to see how good it would do with a simple Javascript Game. Scratch that, I’ve already seen it write some sweet basic Unity games on Youtube!
I just wanted to see how would I go about the process of writing something simple and functional.
Giving Requirements
Also I’ve been writing simple simulation games since time immemorial in languages dating back as far as QBasic and Turbo Pascal (yikes!), so I’m quite familiar with 2D game dev. I wasn’t exactly trying to test its limits here, but I wanted to see how easy would it spit out something baseline and workable
Here was the initial prompt — I’m not a prompt wizard like some of y’all already, but I’m sure I’ll get better with time.
Ok Please generate a tiny java script game that has randomly generated items represented by boxes that a player can consume. The food is represented by circles. When they are generated they are randomly positioned on the map. The board starts out with several food items. The player represented by a square can move around the screen with the direction keys. Please make everything on a dark background. Please add a counter in an 8 bit video game font style that shows how many food that the player ate
And here was the initial code it spit out:
<html>
<body>
<canvas id="game" width="500" height="500"></canvas>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
// Set the background color to black
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Set the font for the counter
ctx.font = '8px "Press Start 2P"';
ctx.fillStyle = 'white';
// Create the player object
const player = {
x: canvas.width / 2,
y: canvas.height / 2,
size: 20,
color: 'white',
score: 0
};
// Create the food objects
const food = [];
for (let i = 0; i < 10; i++) {
food.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: 10,
color: 'red'
});
}
// Draw the player and food on the canvas
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw the player
ctx.fillStyle = player.color;
ctx.fillRect(player.x - player.size / 2, player.y - player.size / 2, player.size, player.size);
// Draw the food
food.forEach(f => {
ctx.beginPath();
ctx.arc(f.x, f.y, f.size, 0, 2 * Math.PI);
ctx.fillStyle = f.color;
ctx.fill();
});
// Draw the score
ctx.fillText(`SCORE: ${player.score}`, 10, 20);
}
// Update the player's position based on the arrow keys
function update() {
if (keys.ArrowUp) {
player.y -= 5;
}
if (keys.ArrowDown) {
player.y += 5;
}
if (keys.ArrowLeft) {
player.x -= 5;
}
if (keys.ArrowRight) {
player.x += 5;
}
}
// Check if the player has collided with any food
function checkCollision() {
food.forEach((f, i) => {
const dx = player.x - f.x;
const dy = player.y - f.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < player.size / 2 + f.size) {
player.score++;
food.splice(i, 1);
}
});
}
// Keep track of which keys are pressed
const keys = {};
window.addEventListener('keydown', e => {
keys[e.code]
});
window.addEventListener('keyup', e => {
delete keys[e.code];
});
// Game loop
function loop() {
update();
checkCollision();
draw();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</script>
</body>
</html>
And the result was workable! But it didn’t do completely what initially asked.
Note: As of writing this, Chat GPT spits out only some of the code, so you have to keep asking it to spit out like the next 30 lines at a time or something. Can get kind of annoying to keep pasting sections (especially when ChatGPTs initial code has errors which it needs to correct and needs to print the whole thing out again), but I’m assuming it’s a limitation they are working on. Also, obviously code can get pretty huge, depending on the ask, so I understand the need for moderation.
Obviously not quite a game yet, here was my second ask:
the food doesn’t randomly generate in different locations over time. Please let the game generate new food. Also make at least some of the food inedible to the player. The inedible food should be a different color. Please give the player a life bar so that if they eat the inedible food their life decreases. If the players health decreases below zero please put game over.
And this was the result:
<html>
<body>
<canvas id="game" width="500" height="500"></canvas>
<audio id="chomp" src="chomp.mp3"></audio>
<audio id="scream" src="scream.mp3"></audio>
<audio id="music" src="music.mp3" loop></audio>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const chomp = document.getElementById('chomp');
const scream = document.getElementById('scream');
const music = document.getElementById('music');
// Set the background color to black
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Set the font for the counter
ctx.font = '8px "Press Start 2P"';
ctx.fillStyle = 'white';
// Draw the opening screen
ctx.fillText('CHAT GPT CHOMPER', canvas.width / 2, canvas.height / 2);
// Create the player object
const player = {
x: canvas.width / 2,
y: canvas.height / 2,
size: 20,
color: 'white',
score: 0,
health: 100
};
// Create the food objects
let food = [];
for (let i = 0; i < 10; i++) {
food.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: 10,
color: 'red',
edible: true
});
}
// Draw the player and food on the canvas
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw the player
ctx.fillStyle = player.color;
ctx.fillRect(player.x - player.size / 2, player.y - player.size / 2, player.size, player.size);
// Draw the food
food.forEach(f => {
ctx.beginPath();
ctx.arc(f.x, f.y, f.size, 0, 2 * Math.PI);
ctx.fillStyle = f.color;
ctx.fill();
});
// Draw the score and health
ctx.fillText(`SCORE: ${player.score}`, 10, 20);
ctx.fillText(`HEALTH: ${player.health}`, 10, 35);
}
// Update the player's position based on the arrow keys
function update() {
if (keys.ArrowUp) {
player.y -= 5;
}
if (keys.ArrowDown) {
player.y += 5;
}
if (keys.ArrowLeft) {
player.x -= 5;
}
if (keys.ArrowRight) {
player.x += 5;
}
}
// Check if the player has collided with any food
function checkCollision() {
food.forEach((f, i) => {
const dx = player.x - f.x;
const dy = player.y - f.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < player.size / 2 + f.size) {
if (f.edible) {
player.score++;
food.splice(i, 1);
chomp.currentTime = 0;
chomp.play();
} else if (f.color === 'gray') {
player.health -= 10;
food.splice(i, 1);
chomp.currentTime = 0;
chomp.play();
} else {
player.health -= 50;
food.splice(i, 1);
scream.currentTime = 0;
scream.play();
}
}
});
}
// Generate new food at random intervals
setInterval(() => {
food.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: 10,
color: 'red',
edible: true
});
}, 1000);
// Generate inedible food at random intervals
setInterval(() => {
food.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: 10,
color: 'gray',
edible: false
});
}, 5000);
// Generate poisonous food at random intervals
setInterval(() => {
food.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: 10,
color: 'purple',
edible: false
});
}, 10000);
// Keep track of which keys are pressed
const keys = {};
window.addEventListener('keydown', e => {
keys[e.code] = true;
});
window.addEventListener('keyup', e => {
delete keys[e.code];
});
// Game loop
function loop() {
update();
checkCollision();
draw();
// End the game if the player's health drops below zero
if (player.health <= 0) {
ctx.fillText('GAME OVER', canvas.width / 2, canvas.height / 2);
return;
}
requestAnimationFrame(loop);
}
// Start the game and music when the player clicks on the canvas
canvas.addEventListener('click', () => {
requestAnimationFrame(loop);
music.currentTime = 0;
music.play();
});
</script>
</body>
</html>
Much better, although the sound doesn’t play because I don’t have local files there. I should have asked it auto-generate the midi sounds using the sound libraries, but maybe next time!
Anyway, here’s the end result game:
Yup! That’s it! Hope you enjoyed! I’m going to try writing more and more complex programs using ChatGPT over the coming weeks, and adding it to my Medium Series!
Stay awesome, and amazed!