Another kinda NSFW post, at least the audio on the video is.
I don’t know how a sane person could keep up with all this stuff. AI Video generation is now almost mature, I couldn’t have imagined a progress this fast.
I didn’t bother with hundred of generations, I stopped with the decent enough stuff and in a few hours this is the final result:
You can watch it on Youtube, if you prefer: Click this link!
As bonus:
This post will not be an exact guide, mostly a collection of what happened in my mind, tips and steps it took to make this fake ad.
I wanted to try AI video gen, but I needed a project and my reader know I love meme projects. My starting idea in this case was the Taste the peaness meme, the double entendre is great. Once I realized I could make a beverage called Pea Pea and use “Taste the peaness” as slogan, it became overfilled with double entendres that worked in English and Italian, too. I know explained jokes stop being fun, but not all my readers know Italian and Italians ranks among the worst in Europe for English knowledge. “PeePee” is an English word for “penis” and “urine”. “Pipì” is the Italian word for “urine”. “Peaness” sound pretty much like “penis” and “Taste the peaness!” is the euphemism that started this post. “Pisello” is the Italian word for “pea”, but it’s also used for “penis”. “Taste the peaness” can translate to “Assaggia/Assapora il pisello” and can hold the same double meaning in both languages.
I started imaging a wine bottle with piss, a jug, etc. In the end I settled for a soda can called Pea Pea Soda.
Flux is a great image model for understanding what I want to do. A prompt as simple as a “A soda can ad shot. The soda brand is Pea Pea Soda” is enough to get the desired result. Image generation AIs are not text AIs, misspelling is common but overall Flux is great with text, lots of generations nail the text.
Now for the video part, there were a few options local and online. Besides a few product shots, ads are often random nonsense. For local generation I was looking into HunYuan, again from the Chinese tech Alibaba, but at the time of writing it does not have any image to video support for the product shots. I tried using it for random shots, it was good at understanding the prompt but not so great in execution. For example hands, hardest part for any AI, were total garbage.
I took one of the worst examples but “Close up shot of an hand opening a soda can” is completely unusable. And to be fair no other AI model got this right.
End the end decided for KlingAI, which is paid but has a few free credits, it does have a new feature called Elements where you put multiple images and you get a video combining images and your prompt. It’s cool it works like magic, or at least for an idiot like me it does look like actual magic.
You can see in the bonus video above the end result of this feature.
I liked this feature so much that I decided that the right workflow was: Generate a Flux image and then use KlingAI to animate that. It worked great: Flux gave me all the random nonsense I asked for and Kling had no troubles adding an animation to that. A soda pouring, people smiling, people dancing in a yellowish rain, a clown holding a glass of soda, a camera pan out. As you saw, I ended up with an handful of good enough videos, a few common errors, like hands flickering or the soda being in the glass before actually pouring. Harold video is great in artefacts: there’s hands flicker, oddly shaped reading glasses, a mug/vase/coat hanger/lamp thing that appear out of nowhere. But until you read this part you didn’t see it and you had to scroll back, didn’t you?
The “Assapora il pisello” writing at the end is a simple edit to make with any graphics or video editor, but I ended up asking Flux to make an underline handwritten text and it was great. It was green text on white background and I had to remove the white background. I probably spent more time doing it this way, but using AI was the point.
For the product name and the Italian translation “Assapora il pisello” any modern text to speech program would have worked, I used Eleven Labs, found a deep Italian voice and that’s it. The ad to be an ad needed a short tune or jingle, in this case I used Suno. The prompt was a simple “80s 90s ad jingle” with the lyrics being only “Taste the peaness!”. I cut it in Audacity and added a fade in at the start, oh god, a manual edit on AI stuff, what kind of monster am I?
For putting together the video clip we don’t currently have an AI enabled video editor. Given the speed of this kind shit comes out lately, we could have one next month. I had to do it the old and hard way but I wasted maybe 10 minutes in OpenShot to sort the clips and add the audio and the result is what you saw at the start of the post.
Nothing useful in this post, just me rambling with myself while having fun. In the previous post Blazing fast game development using LLMs, I talked about a coding LLM called Codestral. Today I took my time to try the new Qwen Coder 32B from the Chinese tech giant Alibaba. Without pasting lots and lots of code, I wanted to share a couple examples it made.
In the first example I asked for another 2D pygame, this time a planet Earth, the Moon orbiting it, and a player controlled spaceship. The LLM delivered almost coherent code, with the only problem being a mixup with global/local variables and a sprite that rotated in the wrong direction and a request to add sprites, sprites that I shamelessly stole from the web.
As a follow up question I asked to add laser shooting. I ended up having this game.
I didn’t want to delve deeper but you can download the code and sprites here:
In a second test I asked it to make a bullet hell game, feature complete (with a start button and a leaderboard), using a single HTML page, and using simple shapes instead of sprites.
It managed to create one single 300 lines page, which I posted here on Pastebin in case you want to look at it. You can save this code in an html file and run it in your browser.
The game is obliviously boring to look at and boring to play, as an AI it doesn’t need dopamine to have fun, well, it doesn’t have a concept of what fun is. What it game me was some sterile code, doing exactly what I asked it to do, my share of fun was getting this all to work.
I keep saying it: AI is advancing too fast, not keeping up will make us humans obsolete. While generative AI will not replace a skilled photographer, writer, or programmer, it’s already good enough to replace the hobbyist to low skilled ones. I used photographer, writer and programmer as example as I feel I’m in the hobby-low skilled range in all three categories and I’m sure AI can already replace people at my level. /Rant end
Today I’m sharing my latest conversation with a LLM, specifically Codestral in this case, about game development. I don’t label myself a game developer, I made a few over the years, I participated in Ludum Dare competitions, but it’s not one of my main hobbies.
My conversation started with a simple prompt like this:
🐮: Don’t waste time talking, only code. Make a pygame pong game.
💻: Sure, here is a simple implementation of the classic Pong game using Pygame:
import pygame
import sys
import random
# Initialize Pygame
pygame.init()
# Set up some constants
WIDTH, HEIGHT = 800, 600
BALL_SPEED = [4, 4]
PADDLE_SPEED = 5
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
# Set up the window
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Pygame Pong')
# Set up the game objects
ball = pygame.Rect(WIDTH // 2 - 15, HEIGHT // 2 - 15, 30, 30)
player = pygame.Rect(WIDTH - 20, HEIGHT // 2 - 70, 10, 140)
opponent = pygame.Rect(10, HEIGHT // 2 - 70, 10, 140)
# Main game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Move the ball
ball.left += BALL_SPEED[0]
ball.top += BALL_SPEED[1]
# Collision with walls
if ball.top <= 0 or ball.bottom >= HEIGHT:
BALL_SPEED[1] = -BALL_SPEED[1]
if ball.left <= 0 or ball.right >= WIDTH:
BALL_SPEED = [4, 4]
ball.center = (WIDTH // 2, HEIGHT // 2)
# Collision with paddles
if ball.colliderect(player) or ball.colliderect(opponent):
BALL_SPEED[0] = -BALL_SPEED[0]
# Move the player paddle
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
player.top -= PADDLE_SPEED
if keys[pygame.K_DOWN]:
player.top += PADDLE_SPEED
# Move the opponent paddle (AI)
if opponent.top < ball.y:
opponent.top += PADDLE_SPEED
elif opponent.bottom > ball.y:
opponent.top -= PADDLE_SPEED
# Draw everything
screen.fill(BLACK)
pygame.draw.ellipse(screen, WHITE, ball)
pygame.draw.rect(screen, WHITE, player)
pygame.draw.rect(screen, WHITE, opponent)
# Flip the display
pygame.display.flip()
This game uses two paddles (one controlled by the user and one by a simple AI). The ball bounces off the walls and paddles. If the ball hits the left or right edge of the screen, it resets to the center.
Now, this isn’t rocket science, Pong is considered the “Hello World!” of coding games, but I never ever programmed something from scratch in Python and I have absolutely zero knowledge of Pygame libraries. Making even a simple Pong game would have required at least a couple hours of reading documentation or a good tutorial. Codestral delivered a neatly commented code in a few seconds. If you run this code through python, the game work, but it has a noticeable problem: it runs at like a million frame per seconds. Let me try telling the LLM to add a frame limiter.
🐮: add a frame limiter
💻: Sure, here is the same Pong game code with a frame limiter added:
import pygame
import sys
import random
# Initialize Pygame
pygame.init()
# Set up some constants
WIDTH, HEIGHT = 800, 600
BALL_SPEED = [4, 4]
PADDLE_SPEED = 5
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
FPS = 60 # Frames per second
# Set up the window
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Pygame Pong')
# Set up the game objects
ball = pygame.Rect(WIDTH // 2 - 15, HEIGHT // 2 - 15, 30, 30)
player = pygame.Rect(WIDTH - 20, HEIGHT // 2 - 70, 10, 140)
opponent = pygame.Rect(10, HEIGHT // 2 - 70, 10, 140)
# Create a clock object to control the frame rate
clock = pygame.time.Clock()
# Main game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Move the ball
ball.left += BALL_SPEED[0]
ball.top += BALL_SPEED[1]
# Collision with walls
if ball.top <= 0 or ball.bottom >= HEIGHT:
BALL_SPEED[1] = -BALL_SPEED[1]
if ball.left <= 0 or ball.right >= WIDTH:
BALL_SPEED = [4, 4]
ball.center = (WIDTH // 2, HEIGHT // 2)
# Collision with paddles
if ball.colliderect(player) or ball.colliderect(opponent):
BALL_SPEED[0] = -BALL_SPEED[0]
# Move the player paddle
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
player.top -= PADDLE_SPEED
if keys[pygame.K_DOWN]:
player.top += PADDLE_SPEED
# Move the opponent paddle (AI)
if opponent.top < ball.y:
opponent.top += PADDLE_SPEED
elif opponent.bottom > ball.y:
opponent.top -= PADDLE_SPEED
# Draw everything
screen.fill(BLACK)
pygame.draw.ellipse(screen, WHITE, ball)
pygame.draw.rect(screen, WHITE, player)
pygame.draw.rect(screen, WHITE, opponent)
# Flip the display and limit the frame rate
pygame.display.flip()
clock.tick(FPS)
The game will now run at a maximum of 60 frames per second (fps), which can help improve performance and make the game smoother.
Again, I know nothing about python/pygame, the LLM knows better and decides to add a clock.tick(FPS) at the end of the main loop, and sets the FPS constant grouped with the other ones at the top. All I had to do was to ask. Now the game is actually playable, but I don’t want the game to start automatically and I want a score system with a win condition.
🐮: Add a start button. Add a score system. Add a win condition for when the player or cpu reaches 5 goals.
💻: Sure, I’ve added these changes to the code:
import pygame
import sys
import random
# Initialize Pygame
pygame.init()
# Set up some constants
WIDTH, HEIGHT = 800, 600
BALL_SPEED = [4, 4]
PADDLE_SPEED = 5
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
FPS = 60 # Frames per second
# Set up the window
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Pygame Pong')
# Set up game variables
player_score = 0
opponent_score = 0
game_started = False
# Font for the score text
font = pygame.font.Font(None, 36)
def draw_text(text, font, color, x, y):
img = font.render(text, True, color)
screen.blit(img, (x, y))
# Set up the game objects
ball = pygame.Rect(WIDTH // 2 - 15, HEIGHT // 2 - 15, 30, 30)
player = pygame.Rect(WIDTH - 20, HEIGHT // 2 - 70, 10, 140)
opponent = pygame.Rect(10, HEIGHT // 2 - 70, 10, 140)
start_button = pygame.Rect(WIDTH // 2 - 50, HEIGHT // 2, 100, 50)
# Create a clock object to control the frame rate
clock = pygame.time.Clock()
# Main game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN and not game_started:
# Start the game when clicking the start button
if start_button.collidepoint(event.pos):
game_started = True
if game_started:
# Move the ball
ball.left += BALL_SPEED[0]
ball.top += BALL_SPEED[1]
# Collision with walls
if ball.top <= 0 or ball.bottom >= HEIGHT:
BALL_SPEED[1] = -BALL_SPEED[1]
if ball.left <= 0:
player_score += 1
ball = pygame.Rect(WIDTH // 2 - 15, HEIGHT // 2 - 15, 30, 30)
BALL_SPEED = [4, 4]
elif ball.right >= WIDTH:
opponent_score += 1
ball = pygame.Rect(WIDTH // 2 - 15, HEIGHT // 2 - 15, 30, 30)
BALL_SPEED = [-4, 4]
# Collision with paddles
if ball.colliderect(player):
BALL_SPEED[0] = -BALL_SPEED[0]
elif ball.collidererect(opponent):
BALL_SPEED[0] = -BALL_SPEED[0]
# Move the player paddle with keyboard
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
player.top -= PADDLE_SPEED
if keys[pygame.K_DOWN]:
player.top += PADDLE_SPEED
else:
# Move the opponent paddle towards the ball (AI)
if opponent.top < ball.y:
opponent.top += PADDLE_SPEED
elif opponent.bottom > ball.y:
opponent.top -= PADDLE_SPEED
# Draw everything
screen.fill(BLACK)
pygame.draw.ellipse(screen, WHITE, ball)
pygame.draw.rect(screen, WHITE, player)
pygame.draw.rect(screen, WHITE, opponent)
draw_text("Player: " + str(player_score), font, WHITE, 10, 10)
draw_text("CPU: " + str(opponent_score), font, WHITE, WIDTH - 90, 10)
# Draw start button if the game hasn't started yet
if not game_started:
pygame.draw.rect(screen, WHITE, start_button)
draw_text("START", font, BLACK, WIDTH // 2 - 30, HEIGHT // 2 + 15)
# Check win condition
if player_score >= 5:
print("Player wins!")
game_started = False
player_score = 0
opponent_score = 0
elif opponent_score >= 5:
print("CPU wins!")
game_started = False
player_score = 0
opponent_score = 0
# Flip the display and limit the frame rate
pygame.display.flip()
clock.tick(FPS)
Now, there is a start button that appears when the game hasn’t started yet. After clicking this button, the game will begin. A score system has been added, which increases the player’s or CPU’s score by one every time they score a goal. The win condition has also been implemented: If either the player or the CPU reaches a score of 5 goals, the respective win message will be printed and the game will reset for a new round.
This bunch of multiplicated 0s an 1s absolutely delivered what I asked for. This time the code doesn’t run, tho, and required manual intervention: – There was and odd typo to fix, the LLM calls colliders colliderect, and in the typo collidererect at line #72 there’s two extra characters. Luckily python outputted to my cmd the line, the error and the possible fix. – The AI paddle didn’t move after I clicked the Start, which was caused by a stray else statement, at line #81. This one required me too actually look where the paddle moving code was in the code.
Now I have a complete game:
A couple things remain to be fixed: the ball and AI paddle move at the same speed making impossible for the player to score a goal and the win condition is outputted into the console instead of ingame. Why do I have to do the heavy lifting?
🐮: There are three things to fix: The AI paddle is to fast compared to the ball; The AI paddle doesn’t move after I press start; Player/CPU wins should be outputted in an ingame box, not into the console.
💻: Sure, let’s make these modifications. 1. Let’s slow down the opponent’s paddle by using a smaller speed factor for it. 2. To make sure the AI paddle moves after we press start, I will move its motion inside of our main game loop and include a condition to check if the game has started. 3. For displaying the winner within the game screen, I’ll add some text that says “Player wins!” or “CPU wins!”. This will be drawn on the screen using pygame’s font rendering functionality. When either player reaches 5 goals, we’ll set a flag to indicate that the game is over and display the win message in each frame until a new game starts
Let me make these changes for you.
import pygame
import sys
import random
# Initialize Pygame
pygame.init()
# Set up some constants
WIDTH, HEIGHT = 800, 600
BALL_SPEED = [4, 4]
PADDLE_SPEED = 5
AI_PADDLE_SPEED = 3 # Slowing down the AI paddle
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
FPS = 60 # Frames per second
# Set up the window
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Pygame Pong')
# Set up game variables
player_score = 0
opponent_score = 0
game_started = False
game_over = False # New flag for when the game is over
winner = None # Variable to store the winner
# Font for the score text
font = pygame.font.Font(None, 36)
def draw_text(text, font, color, x, y):
img = font.render(text, True, color)
screen.blit(img, (x, y))
# Set up the game objects
ball = pygame.Rect(WIDTH // 2 - 15, HEIGHT // 2 - 15, 30, 30)
player = pygame.Rect(WIDTH - 20, HEIGHT // 2 - 70, 10, 140)
opponent = pygame.Rect(10, HEIGHT // 2 - 70, 10, 140)
start_button = pygame.Rect(WIDTH // 2 - 50, HEIGHT // 2, 100, 50) # Start button rectangle object
# Create a clock object to control the frame rate
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN and not game_started: # Check if the mouse was clicked and the game hasn't started yet
if start_button.collidepoint(event.pos): # If the click was on the start button, then start the game
game_started = True
keys = pygame.key.get_pressed()
if keys[pygame.K_UP] and player.top > 0:
player.move_ip(0, -PADDLE_SPEED)
if keys[pygame.K_DOWN] and player.bottom < HEIGHT:
player.move_ip(0, PADDLE_SPEED)
# Move the AI paddle if the game has started
if game_started:
if ball.centery > opponent.centery + AI_PADDLE_SPEED // 2 and opponent.bottom < HEIGHT:
opponent.move_ip(0, AI_PADDLE_SPEED)
elif ball.centery < opponent.centery - AI_PADDLE_SPEED // 2 and opponent.top > 0:
opponent.move_ip(0, -AI_PADDLE_SPEED)
# Move the ball if the game has started and isn't over
if game_started and not game_over:
ball.move_ip(*BALL_SPEED)
if ball.left <= 0 or ball.right >= WIDTH:
BALL_SPEED[0] = -BALL_SPEED[0]
if ball.left <= 0:
player_score += 1
else:
opponent_score += 1
if ball.top <= 0 or ball.bottom >= HEIGHT:
BALL_SPEED[1] = -BALL_SPEED[1]
if ball.colliderect(player) or ball.colliderect(opponent):
BALL_SPEED[0] = -BALL_SPEED[0]
# Draw everything on the screen
screen.fill(BLACK)
pygame.draw.rect(screen, WHITE, player)
pygame.draw.rect(screen, WHITE, opponent)
pygame.draw.ellipse(screen, WHITE, ball)
draw_text("Player: " + str(player_score), font, WHITE, 10, 10)
draw_text("CPU: " + str(opponent_score), font, WHITE, WIDTH - 90, 10)
# Draw the start button if the game hasn't started yet
if not game_started and not game_over:
pygame.draw.rect(screen, WHITE, start_button)
draw_text("START", font, BLACK, WIDTH // 2 - 30, HEIGHT // 2 + 15)
# If the game is over, display the winner message in the center of the screen
elif game_over:
draw_text(winner + " wins!", font, WHITE, WIDTH // 2 - 80, HEIGHT // 2)
# Check if either player has reached 5 points and end the game if so
if player_score >= 5:
winner = "Player"
game_over = True
game_started = False
player_score = 0
opponent_score = 0
elif opponent_score >= 5:
winner = "CPU"
game_over = True
game_started = False
player_score = 0
opponent_score = 0
# If the game is over and we press enter, reset the game state
if keys[pygame.K_RETURN] and game_over:
winner = None
game_over = False
ball.center = (WIDTH // 2, HEIGHT // 2)
player.center = (50, HEIGHT // 2)
opponent.center = (WIDTH - 50, HEIGHT // 2)
BALL_SPEED = [random.choice([-4, 4]), random.choice([-4, 4])]
pygame.display.update()
clock.tick(60)
This is a simple implementation of a pong game in Python using the Pygame library. The player can move their paddle up and down to hit the ball back towards their opponent (the computer). When the ball hits one of the sides of the screen, a point is scored for the other player. If either player reaches 5 points, they win and the game ends. Pressing enter will reset the game state so that you can play again. The AI paddle is controlled by moving it towards the center of the ball’s y-coordinate if it is above or below the center of the paddle. This gives the computer a simple but effective strategy for hitting the ball back towards the player. The speed at which the ball and paddles move can be adjusted to change the difficulty of the game.
The newly updated code is playable without any modification. There are a few new problems: – The ball now doesn’t recenter after a goal, the code was actually removed. – You click Start for the first game, but use Enter to reset after a match.
I got bored of toying around and I will stop here, making this blog post took me over an hour, while making the game probably took the AI five minutes at most. I’m incredibly amused with the AI’s skill.
This website uses functional cookies to improve your experience, no personal data is collected while browsing. We'll assume you're ok with this. Cookie settingsACCEPT
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. This site does not use any kind of third-party cookie and absolutely no kind of user tracking. See Privacy & Cookie policy for details.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information. See Privacy & Cookie policy for details.