On May 22nd, Anthropic released Claude's Sonnet 4 and Opus 4. These next-generation Claude models set new standards for coding, advanced reasoning, and AI agents. This time, Claude offers the best coding and problem-solving standards.
With this significant update in the world of AI, it's a perfect time to compare this new model with the ones already doing great in this space, Deepseek R1 and Qwen 3.
Deepseek has been gaining attention for its ability to handle problem-solving and show its work step by step, while Qwen 3 stands out for its strong multilingual understanding and detailed, accurate reasoning. In this blog, we'll take a closer look at what each model is good at, how they differ, and which one might be better for your needs.
Claude 4 and Deepseek R1 are both strong coding models, but they have different strengths. Claude 4 is great for creating realistic, production-ready code that integrates well with real-world tools. On the other hand, Deepseek R1 is excellent for open-source projects and has strong math and coding skills, but it seems more academic and less refined for practical UI or full-stack development.
Anthropic recently released Claude 4, which includes two models: Opus 4 and Sonnet 4. Both have made a strong impression on developers and AI enthusiasts.
Claude Opus 4 is their most advanced model so far, known for handling long, complex coding tasks with accuracy and precision.
In testing, it outperformed all other models on real-world software engineering benchmarks, including SWE-bench, where it scored an impressive 72.7%. Claude Sonnet 4 also showed major improvements over the previous Sonnet 3.7, offering faster, more precise responses and better understanding of developer instructions.
But what makes Claude 4 stand out isn't just the benchmarks. It's the way both models handle real codebases. From solving multi-file issues to fixing deep architectural problems without shortcuts, Claude 4 feels like a step closer to having a true coding partner.
Here's what makes Claude 4 a true coding partner:
If you're looking for an AI that truly understands code and doesn't just patch things at the surface, Claude 4 is worth a try.
DeepSeek R1 is a standout open-source AI model from China, gaining global attention for its impressive performance and affordability. Built with a unique Mixture-of-Experts (MoE) architecture, it activates only 37 billion of its 671 billion parameters per task, ensuring efficient computation without compromising capability.
In benchmark tests, DeepSeek R1 excels: it achieved a 97.3% accuracy on the MATH-500 benchmark, surpassing many competitors, and scored 96.3% on Codeforces, demonstrating strong coding proficiency. Its reasoning abilities are also notable, with a 90.8% score on the MMLU benchmark, closely rivaling leading models.
What sets DeepSeek R1 apart is its accessibility. Released under an open-source MIT license, it's freely available for use and modification. Additionally, its API is cost-effective, priced at approximately $0.55 per million input tokens and $2.19 per million output tokens, making advanced AI more accessible to developers and businesses alike.
DeepSeek R1 is a big step in making AI more accessible, providing strong performance without the usual high costs of these models.
Qwen 3 is the latest generation of open-weight large language models from Alibaba, designed to deliver high performance across a wide range of tasks, including coding, math, multilingual reasoning, and agentic workflows. The flagship MoE model, Qwen3-235B-A22B, with 22B activated parameters, performs competitively with top-tier models like DeepSeek-R1, o1, o3-mini, Grok-3, and Gemini 2.5 Pro. Even its smaller variants, like Qwen3-4B, rival much larger models such as Qwen2.5-72 B.
Qwen 3 comes in both dense and MoE variants, all open-weighted under the Apache 2.0 license. With support for 128K context length, 119 languages and dialects, and a flexible hybrid thinking mode (step-by-step reasoning or fast response), Qwen 3 is built to be adaptable, efficient, and powerful.
Key features:
Qwen 3 is available on major platforms like Hugging Face, ModelScope, and Kaggle. It integrates smoothly with tools like Ollama, vLLM, SGLang, and LM Studio, making it easy to use in local or cloud environments.
We briefly looked at the capabilities of the Deepseek R1 and Claude Sonnet 4. Now it's time to test both of them. We'll give the same type of coding prompt to each and see how they perform.
So, let's start with the first task.
Let's start with Deepseek R1. I am going to give this prompt:
Prompt: Create a 3D simulation of the solar system. Planets should revolve around the sun and rotate on their axes. Bonus if each planet's speed and size are somewhat realistic. In HTML, CSS, JS, and with Three JS
And, it came with this result.
Yes, it's good, but a lot of improvement is needed. Because currently it's not looking that attractive and real.
Code:
<!DOCTYPE html>
<html>
<head>
<title>3D Solar System</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
<script>
let scene, camera, renderer, controls;
class Planet {
constructor(radius, distance, orbitalSpeed, rotationSpeed, color) {
this.radius = radius;
this.distance = distance;
this.orbitalSpeed = orbitalSpeed;
this.rotationSpeed = rotationSpeed;
this.angle = Math.random() * Math.PI * 2;
this.mesh = new THREE.Mesh(
new THREE.SphereGeometry(radius, 32, 32),
new THREE.MeshPhongMaterial({ color })
);
this.mesh.position.x = distance;
scene.add(this.mesh);
}
update() {
this.angle += this.orbitalSpeed;
this.mesh.position.x = Math.cos(this.angle) * this.distance;
this.mesh.position.z = Math.sin(this.angle) * this.distance;
this.mesh.rotation.y += this.rotationSpeed;
}
}
function init() {
// Scene setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Lighting
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const sunLight = new THREE.PointLight(0xffffff, 1.5);
scene.add(sunLight);
// Camera controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
camera.position.z = 50;
// Create Sun (scaled down for visualization)
const sunGeometry = new THREE.SphereGeometry(4, 32, 32);
const sunMaterial = new THREE.MeshBasicMaterial({
color: 0xffff00,
emissive: 0xffff00,
emissiveIntensity: 0.5
});
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
scene.add(sun);
// Create planets (relative sizes and speeds)
// Parameters: radius, distance, orbital speed, rotation speed, color
const planets = [
new Planet(0.4, 8, 0.03, 0.02, 0x808080), // Mercury
new Planet(0.9, 11, 0.024, 0.015, 0xffd700), // Venus
new Planet(1.0, 15, 0.02, 0.01, 0x0000ff), // Earth
new Planet(0.5, 18, 0.017, 0.008, 0xff0000), // Mars
new Planet(2.2, 25, 0.013, 0.025, 0xffa500), // Jupiter
new Planet(1.8, 32, 0.009, 0.02, 0xffd700), // Saturn
new Planet(0.8, 37, 0.007, 0.015, 0x00ffff), // Uranus
new Planet(0.7, 42, 0.005, 0.015, 0x0000ff) // Neptune
];
// Animation loop
function animate() {
requestAnimationFrame(animate);
planets.forEach(planet => planet.update());
controls.update();
renderer.render(scene, camera);
}
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
animate();
}
init();
</script>
</body>
</html>
I used the same prompt for Claude as well. And, it came up with this result.
This one is quite strange. It doesn't show orbits, I can't zoom in, and the planets mostly look black and too small to see clearly. So, we might need to give Qwen 3 more detailed instructions to create this 3D Solar System.
I used the same prompt for Qwen3 as well. And, it came up with this result.
This one is quite strange. It doesn't show orbits, I can't zoom in, and the planets mostly look black and too small to see clearly. So, we might need to give Claude 4 more detailed instructions to create this 3D Solar System.
Code:
import React, { useRef, useEffect } from 'react';
import * as THREE from 'three';
const App = () => {
const mountRef = useRef(null);
useEffect(() => {
// Scene Setup
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 50;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
mountRef.current.appendChild(renderer.domElement);
// Lighting
const ambientLight = new THREE.AmbientLight(0x404040); // soft white light
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 2, 100);
pointLight.position.set(0, 0, 0);
scene.add(pointLight);
// Sun
const sunGeometry = new THREE.SphereGeometry(5, 32, 32);
const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffcc33 });
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
scene.add(sun);
// Planet Data (realistic relative sizes and speeds)
const planetsData = [
{ name: "Mercury", size: 0.38, orbit: 8.4, speed: 8.1, color: 0xadadad },
{ name: "Venus", size: 0.95, orbit: 15.2, speed: 3.2, color: 0xffe699 },
{ name: "Earth", size: 1.0, orbit: 21.5, speed: 2.6, color: 0x3399ff },
{ name: "Mars", size: 0.53, orbit: 32.0, speed: 1.5, color: 0xff6600 },
{ name: "Jupiter", size: 2.7, orbit: 112.0, speed: 0.27, color: 0xffd700 },
{ name: "Saturn", size: 2.2, orbit: 206.0, speed: 0.09, color: 0xf5deb3 },
{ name: "Uranus", size: 1.0, orbit: 400.0, speed: 0.03, color: 0xadd8e6 },
{ name: "Neptune", size: 0.97, orbit: 628.0, speed: 0.015, color: 0x0000cd }
];
const planets = [];
planetsData.forEach(data => {
const geometry = new THREE.SphereGeometry(data.size, 32, 32);
const material = new THREE.MeshStandardMaterial({
color: data.color,
roughness: 0.6,
metalness: 0.4
});
const mesh = new THREE.Mesh(geometry, material);
const orbitGroup = new THREE.Group();
orbitGroup.add(mesh);
scene.add(orbitGroup);
// Position planet in orbit
const angle = Math.random() * Math.PI * 2;
mesh.position.x = Math.cos(angle) * data.orbit;
mesh.position.z = Math.sin(angle) * data.orbit;
planets.push({
mesh,
orbitGroup,
orbitSpeed: data.speed / 10,
rotationSpeed: 0.05 + Math.random() * 0.05,
distance: data.orbit
});
// Orbit ring (optional visual aid)
const orbitRingGeometry = new THREE.RingGeometry(data.orbit - 0.05, data.orbit + 0.05, 64);
const orbitRingMaterial = new THREE.MeshBasicMaterial({ color: 0xaaaaaa, side: THREE.DoubleSide });
const orbitRing = new THREE.Mesh(orbitRingGeometry, orbitRingMaterial);
orbitRing.rotation.x = Math.PI / 2;
scene.add(orbitRing);
});
// Animation loop
const animate = () => {
requestAnimationFrame(animate);
// Rotate sun
sun.rotation.y += 0.005;
// Animate planets
planets.forEach(planet => {
// Orbit around the sun
planet.orbitGroup.rotation.y += planet.orbitSpeed * 0.01;
// Rotate on axis
planet.mesh.rotation.y += planet.rotationSpeed;
});
renderer.render(scene, camera);
};
animate();
// Handle resizing
const handleResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
mountRef.current.removeChild(renderer.domElement);
};
}, []);
return <div ref={mountRef} style={{ width: '100%', height: '100vh' }} />;
};
export default App;
The first task is complete, so let's move on to the next one. We'll start with Claude 4. I used this prompt:
Prompt: Use html css and js and create a fashion website clothing website. Use creative GSAP Animation and make sure the site must be responsive. There will be a landing page with all functionality of add to card and buy and each and everything must be creatively animated using GSAP. Must have option to search product view product different category and view, moving, and going through one page to another must be a animated using GSAP. Animation must be smooth and silky. Also add smooth like buttery scroll animation.
And, Claude 4 comes up with this result.
It created a website with GSAP animation and features for adding items to the cart and checking out. However, it didn't add the images, but it included all the functionality I mentioned. It added features for checkout, adding to cart, adding to favorites, and a search option. Although the site isn't very responsive and uses emojis instead of icons.
The rest is good.
I've used the same prompt with Qwen 3 as well, and this is what it came up with:
The site looks pretty decent. It has products, search functionality, and some images. But, it didn't add most of the functionalities like Claude did, and it doesn't include GSAP animations. Overall, it needs a lot of improvements.
With the same prompt, I tried Deepseek R1, and this is what it came up with:
This result really amazed me. I wasn't expecting this much, but it turned out to be a fabulous fashion website. It uses proper icons, smooth and buttery GSAP animations, and appropriate images by default. The site is fully responsive, and it added a beautiful logo loading animation. Overall, it won me over completely. It's a clear winner in this case.
The only thing it didn't do was the functionality. It didn't add features for checkout, add to cart, or search. So, while the UI works well, it might need a few more prompts to complete the functionality.
Now, let's do one more test with a new prompt. This time, I am going to use this prompt:
Prompt: Make a bullet dodging game (top-down view) using HTML Canvas. The player is a small character that can move in all directions. Bullets shoot from all sides in patterns. The player must avoid being hit for as long as possible. Add increasing difficulty over time.
Let's submit this prompt for Qwen 3 first. And it came up with this result:
It created the game, but when I played, I couldn't move at all. If you watch the video closely, you'll notice I'm trying to move the green ball, but it stays stuck in a specific circular area. So, it didn't work well. Let's check the next ones.
Code:
import React, { useRef, useEffect, useState } from 'react';
const App = () => {
const canvasRef = useRef(null);
const [gameState, setGameState] = useState('menu');
const [score, setScore] = useState(0);
const [highScore, setHighScore] = useState(0);
const [level, setLevel] = useState(1);
const gameLoopRef = useRef(null);
const keys = useRef({ up: false, down: false, left: false, right: false });
// Game constants
const PLAYER_RADIUS = 10;
const BULLET_RADIUS = 6;
const PLAYER_SPEED = 4;
const INITIAL_BULLET_INTERVAL = 1200; // ms
const MIN_BULLET_INTERVAL = 300;
const bullets = useRef([]);
const lastBulletTime = useRef(0);
const startTime = useRef(0);
const lastUpdateTime = useRef(0);
const resetGame = () => {
bullets.current = [];
lastBulletTime.current = 0;
startTime.current = Date.now();
lastUpdateTime.current = Date.now();
setScore(0);
setLevel(1);
setGameState('playing');
};
const spawnBullet = (canvasWidth, canvasHeight) => {
const side = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
let x, y, vx, vy;
switch (side) {
case 0: // top
x = Math.random() * canvasWidth;
y = -BULLET_RADIUS;
break;
case 1: // right
x = canvasWidth + BULLET_RADIUS;
y = Math.random() * canvasHeight;
break;
case 2: // bottom
x = Math.random() * canvasWidth;
y = canvasHeight + BULLET_RADIUS;
break;
case 3: // left
x = -BULLET_RADIUS;
y = Math.random() * canvasHeight;
break;
}
// Aim toward the center of the canvas
const angle = Math.atan2(canvasHeight / 2 - y, canvasWidth / 2 - x);
vx = Math.cos(angle) * 3;
vy = Math.sin(angle) * 3;
bullets.current.push({ x, y, vx, vy });
};
const checkCollision = (x1, y1, r1, x2, y2, r2) => {
const dx = x1 - x2;
const dy = y1 - y2;
return dx * dx + dy * dy <= (r1 + r2) ** 2;
};
const update = (playerX, playerY, canvasWidth, canvasHeight, deltaTime) => {
// Update bullets
for (const bullet of bullets.current) {
bullet.x += bullet.vx;
bullet.y += bullet.vy;
}
// Remove off-screen bullets
bullets.current = bullets.current.filter(bullet =>
bullet.x >= -BULLET_RADIUS &&
bullet.x <= canvasWidth + BULLET_RADIUS &&
bullet.y >= -BULLET_RADIUS &&
bullet.y <= canvasHeight + BULLET_RADIUS
);
// Check collision with player
for (const bullet of bullets.current) {
if (checkCollision(playerX, playerY, PLAYER_RADIUS, bullet.x, bullet.y, BULLET_RADIUS)) {
endGame();
return;
}
}
// Update score and level
const currentElapsedTime = Date.now() - startTime.current;
const newScore = Math.floor(currentElapsedTime / 1000);
if (newScore !== score) {
setScore(newScore);
// Increase difficulty every 10 seconds
if (newScore % 10 === 0) {
const newLevel = Math.min(5, Math.floor(newScore / 10) + 1);
if (newLevel > level) {
setLevel(newLevel);
}
}
}
};
const endGame = () => {
setGameState('gameOver');
if (score > highScore) {
setHighScore(score);
}
// Reset for next game
cancelAnimationFrame(gameLoopRef.current);
};
const draw = (ctx, canvasWidth, canvasHeight, playerX, playerY) => {
// Clear canvas
ctx.fillStyle = '#1a1a1a';
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Draw player
ctx.beginPath();
ctx.arc(playerX, playerY, PLAYER_RADIUS, 0, Math.PI * 2);
ctx.fillStyle = '#4ade80';
ctx.fill();
// Draw bullets
for (const bullet of bullets.current) {
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, BULLET_RADIUS, 0, Math.PI * 2);
ctx.fillStyle = '#ef4444';
ctx.fill();
}
// Draw HUD
ctx.fillStyle = '#ffffff';
ctx.font = '16px sans-serif';
ctx.fillText(`Score: ${score}`, 10, 25);
ctx.fillText(`Level: ${level}`, 10, 50);
ctx.fillText(`High Score: ${highScore}`, 10, 75);
};
const gameLoop = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
const currentTime = Date.now();
const deltaTime = currentTime - lastUpdateTime.current;
lastUpdateTime.current = currentTime;
// Calculate player position based on keys
let playerX = canvasWidth / 2;
let playerY = canvasHeight / 2;
if (keys.current.up) playerY -= PLAYER_SPEED;
if (keys.current.down) playerY += PLAYER_SPEED;
if (keys.current.left) playerX -= PLAYER_SPEED;
if (keys.current.right) playerX += PLAYER_SPEED;
// Keep player within bounds
playerX = Math.max(PLAYER_RADIUS, Math.min(canvasWidth - PLAYER_RADIUS, playerX));
playerY = Math.max(PLAYER_RADIUS, Math.min(canvasHeight - PLAYER_RADIUS, playerY));
// Spawn bullets based on level and timing
const currentInterval = Math.max(MIN_BULLET_INTERVAL, INITIAL_BULLET_INTERVAL - (level - 1) * 200);
if (currentTime - lastBulletTime.current > currentInterval) {
spawnBullet(canvasWidth, canvasHeight);
lastBulletTime.current = currentTime;
}
// Update game state
update(playerX, playerY, canvasWidth, canvasHeight, deltaTime);
// Draw everything
draw(ctx, canvasWidth, canvasHeight, playerX, playerY);
if (gameState === 'playing') {
gameLoopRef.current = requestAnimationFrame(gameLoop);
}
};
// Event handlers
useEffect(() => {
const handleKeyDown = (e) => {
switch (e.key.toLowerCase()) {
case 'w':
case 'arrowup':
keys.current.up = true;
break;
case 's':
case 'arrowdown':
keys.current.down = true;
break;
case 'a':
case 'arrowleft':
keys.current.left = true;
break;
case 'd':
case 'arrowright':
keys.current.right = true;
break;
}
};
const handleKeyUp = (e) => {
switch (e.key.toLowerCase()) {
case 'w':
case 'arrowup':
keys.current.up = false;
break;
case 's':
case 'arrowdown':
keys.current.down = false;
break;
case 'a':
case 'arrowleft':
keys.current.left = false;
break;
case 'd':
case 'arrowright':
keys.current.right = false;
break;
}
};
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
return () => {
window.removeEventListener('keydown', handleKeyDown);
window.removeEventListener('keyup', handleKeyUp);
};
}, []);
// Resize canvas to fit window
useEffect(() => {
const resizeCanvas = () => {
const canvas = canvasRef.current;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
return () => window.removeEventListener('resize', resizeCanvas);
}, []);
// Start game loop when playing
useEffect(() => {
if (gameState === 'playing') {
lastUpdateTime.current = Date.now();
startTime.current = Date.now();
gameLoopRef.current = requestAnimationFrame(gameLoop);
}
return () => {
if (gameLoopRef.current) {
cancelAnimationFrame(gameLoopRef.current);
}
};
}, [gameState]);
return (
<div className="relative w-full h-full">
<canvas ref={canvasRef} className="fixed inset-0" tabIndex="0" />
{/* Menu Screen */}
{gameState === 'menu' && (
<div className="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-70 text-white p-4">
<h1 className="text-4xl md:text-6xl font-bold mb-6 text-center">Bullet Dodger</h1>
<p className="text-xl md:text-2xl mb-8 text-center max-w-md">
Avoid the bullets for as long as you can! Use arrow keys or WASD to move.
</p>
<button
onClick={resetGame}
className="px-8 py-3 bg-green-500 hover:bg-green-600 rounded-lg text-xl font-semibold transition-colors"
>
Start Game
</button>
</div>
)}
{/* Game Over Screen */}
{gameState === 'gameOver' && (
<div className="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-70 text-white p-4">
<h2 className="text-4xl md:text-6xl font-bold mb-4">Game Over</h2>
<p className="text-2xl md:text-3xl mb-2">Score: {score}</p>
<p className="text-xl mb-6">High Score: {highScore}</p>
<button
onClick={resetGame}
className="px-8 py-3 bg-blue-500 hover:bg-blue-600 rounded-lg text-xl font-semibold transition-colors"
>
Play Again
</button>
</div>
)}
</div>
);
};
export default App;
Let's submit this prompt for Deepseek R1. And it came up with this result:
This looks good. The Neon UI is nice, and the movement of the player and enemies is smooth. If you watch the video closely, you can see that when I move the player, it leaves traces behind, so I know where I started and how much area I've covered. The difficulty increases automatically based on how long I survive. Overall, I really liked this one.
Code:
<!DOCTYPE html>
<html>
<head>
<title>Neon Bullet Dodge</title>
<style>
body {
margin: 0;
padding: 0;
background: #0a0a1a;
color: white;
font-family: 'Audiowide', cursive;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
#game-container {
position: relative;
box-shadow: 0 0 30px #00f7ff;
border-radius: 10px;
overflow: hidden;
}
canvas {
display: block;
background: #121230;
}
#ui {
position: absolute;
top: 20px;
left: 0;
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 30px;
box-sizing: border-box;
pointer-events: none;
}
#score, #time {
font-size: 24px;
text-shadow: 0 0 10px #00f7ff;
background: rgba(0, 10, 20, 0.7);
padding: 5px 15px;
border-radius: 20px;
border: 1px solid #00f7ff;
}
#game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
}
#game-over h1 {
font-size: 48px;
color: #ff3366;
text-shadow: 0 0 15px #ff0066;
margin-bottom: 20px;
}
#final-score {
font-size: 32px;
margin-bottom: 30px;
color: #00f7ff;
}
button {
background: linear-gradient(45deg, #0066ff, #00f7ff);
border: none;
color: white;
padding: 15px 40px;
font-size: 18px;
border-radius: 30px;
cursor: pointer;
font-family: 'Audiowide', cursive;
transition: all 0.3s;
box-shadow: 0 0 15px #00f7ff;
}
button:hover {
transform: scale(1.05);
box-shadow: 0 0 25px #00f7ff;
}
#controls {
position: absolute;
bottom: 30px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
}
.particle {
position: absolute;
border-radius: 50%;
pointer-events: none;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Audiowide&display=swap" rel="stylesheet">
</head>
<body>
<div id="game-container">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="ui">
<div id="score">Score: 0</div>
<div id="time">Time: 0s</div>
</div>
<div id="game-over">
<h1>GAME OVER</h1>
<div id="final-score">Score: 0</div>
<button id="restart">PLAY AGAIN</button>
</div>
<div id="controls">WASD or Arrow Keys to Move</div>
</div>
<script>
// Game Configuration
const config = {
player: {
radius: 12,
speed: 6,
color: '#00f7ff',
trailLength: 15
},
bullets: {
baseSpeed: 2,
speedIncrease: 0.002,
maxSpeed: 8,
spawnRate: 60, // frames
spawnRateDecrease: 0.5,
minSpawnRate: 20,
colors: ['#ff3366', '#ff9900', '#ff00ff', '#00ff99']
},
difficulty: {
increaseInterval: 300, // frames
bulletCountIncrease: 0.2,
maxBulletCount: 5
}
};
// Game Elements
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const timeElement = document.getElementById('time');
const gameOverScreen = document.getElementById('game-over');
const finalScoreElement = document.getElementById('final-score');
const restartButton = document.getElementById('restart');
// Game State
let player = {
x: 400,
y: 300,
trail: []
};
let bullets = [];
let keys = {};
let score = 0;
let gameTime = 0;
let isGameActive = false;
let animationFrameId;
let spawnCounter = 0;
let difficultyLevel = 1;
// Initialize
function init() {
// Event Listeners
document.addEventListener('keydown', e => keys[e.key.toLowerCase()] = true);
document.addEventListener('keyup', e => keys[e.key.toLowerCase()] = false);
restartButton.addEventListener('click', startGame);
// Start the game
startGame();
}
function startGame() {
// Reset game state
player = {
x: 400,
y: 300,
trail: []
};
bullets = [];
score = 0;
gameTime = 0;
spawnCounter = 0;
difficultyLevel = 1;
isGameActive = true;
// Update UI
scoreElement.textContent = `Score: ${score}`;
timeElement.textContent = `Time: 0s`;
gameOverScreen.style.display = 'none';
// Start game loop
if (animationFrameId) cancelAnimationFrame(animationFrameId);
gameLoop();
}
function spawnBullet() {
const side = Math.floor(Math.random() * 4);
let x, y, angle;
// Random spawn position on edges
switch(side) {
case 0: // Top
x = Math.random() * canvas.width;
y = -10;
angle = Math.PI/2 + (Math.random() - 0.5) * Math.PI/1.5;
break;
case 1: // Right
x = canvas.width + 10;
y = Math.random() * canvas.height;
angle = Math.PI + (Math.random() - 0.5) * Math.PI/1.5;
break;
case 2: // Bottom
x = Math.random() * canvas.width;
y = canvas.height + 10;
angle = -Math.PI/2 + (Math.random() - 0.5) * Math.PI/1.5;
break;
case 3: // Left
x = -10;
y = Math.random() * canvas.height;
angle = 0 + (Math.random() - 0.5) * Math.PI/1.5;
break;
}
const speed = Math.min(
config.bullets.baseSpeed + (gameTime * config.bullets.speedIncrease),
config.bullets.maxSpeed
);
const color = config.bullets.colors[
Math.floor(Math.random() * config.bullets.colors.length)
];
bullets.push({
x, y,
radius: 6,
speed: speed,
color: color,
angle: angle,
glow: 0
});
}
function updatePlayer() {
// Movement
const moveX = (keys.arrowright || keys.d ? 1 : 0) - (keys.arrowleft || keys.a ? 1 : 0);
const moveY = (keys.arrowdown || keys.s ? 1 : 0) - (keys.arrowup || keys.w ? 1 : 0);
// Normalize diagonal movement
if (moveX !== 0 && moveY !== 0) {
player.x += moveX * config.player.speed * 0.707; // 1/sqrt(2)
player.y += moveY * config.player.speed * 0.707;
} else {
player.x += moveX * config.player.speed;
player.y += moveY * config.player.speed;
}
// Keep player in bounds
player.x = Math.max(config.player.radius, Math.min(canvas.width - config.player.radius, player.x));
player.y = Math.max(config.player.radius, Math.min(canvas.height - config.player.radius, player.y));
// Update trail
player.trail.unshift({x: player.x, y: player.y});
if (player.trail.length > config.player.trailLength) {
player.trail.pop();
}
}
function updateBullets() {
bullets.forEach((bullet, index) => {
// Update position
bullet.x += Math.cos(bullet.angle) * bullet.speed;
bullet.y += Math.sin(bullet.angle) * bullet.speed;
// Update glow effect
bullet.glow = (bullet.glow + 0.05) % (Math.PI * 2);
// Remove off-screen bullets
if (bullet.x < -50 || bullet.x > canvas.width + 50 ||
bullet.y < -50 || bullet.y > canvas.height + 50) {
bullets.splice(index, 1);
}
// Collision detection
const dx = player.x - bullet.x;
const dy = player.y - bullet.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < config.player.radius + bullet.radius) {
gameOver();
createExplosion(player.x, player.y, bullet.color);
}
});
}
function increaseDifficulty() {
gameTime++;
// Update score and time display
score = Math.floor(gameTime / 1000);
level = Math.floor(gameTime / 10000) + 1;
// Increase difficulty periodically
if (gameTime % config.difficulty.increaseInterval === 0) {
difficultyLevel += 1;
const newSpawnRate = Math.max(
config.bullets.minSpawnRate,
config.bullets.spawnRate - (difficultyLevel * config.bullets.spawnRateDecrease)
);
// Spawn more bullets
const bulletsToSpawn = Math.min(
Math.floor(difficultyLevel * config.difficulty.bulletCountIncrease),
config.difficulty.maxBulletCount
);
for (let i = 0; i < bulletsToSpawn; i++) {
setTimeout(spawnBullet, i * 100);
}
}
}
function gameOver() {
isGameActive = false;
finalScoreElement.textContent = `Score: ${score}`;
gameOverScreen.style.display = 'flex';
cancelAnimationFrame(animationFrameId);
}
function createExplosion(x, y, color) {
const particleCount = 30;
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
const size = Math.random() * 10 + 5;
const angle = Math.random() * Math.PI * 2;
const speed = Math.random() * 5 + 2;
const lifetime = Math.random() * 1000 + 500;
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
particle.style.background = color;
particle.style.left = `${x}px`;
particle.style.top = `${y}px`;
document.getElementById('game-container').appendChild(particle);
const startTime = Date.now();
function updateParticle() {
const elapsed = Date.now() - startTime;
const progress = elapsed / lifetime;
if (progress >= 1) {
particle.remove();
return;
}
const currentX = x + Math.cos(angle) * speed * progress * 100;
const currentY = y + Math.sin(angle) * speed * progress * 100;
const currentOpacity = 1 - progress;
const currentSize = size * (1 - progress);
particle.style.transform = `translate(${currentX - x}px, ${currentY - y}px)`;
particle.style.opacity = currentOpacity;
particle.style.width = `${currentSize}px`;
particle.style.height = `${currentSize}px`;
requestAnimationFrame(updateParticle);
}
requestAnimationFrame(updateParticle);
}
}
function drawPlayer() {
// Draw trail
ctx.globalAlpha = 0.3;
player.trail.forEach((pos, i) => {
const alpha = i / player.trail.length;
const radius = config.player.radius * alpha;
ctx.beginPath();
ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);
ctx.fillStyle = config.player.color;
ctx.fill();
});
ctx.globalAlpha = 1;
// Draw player
ctx.beginPath();
ctx.arc(player.x, player.y, config.player.radius, 0, Math.PI * 2);
ctx.fillStyle = config.player.color;
ctx.shadowBlur = 15;
ctx.shadowColor = config.player.color;
ctx.fill();
ctx.shadowBlur = 0;
// Inner glow
ctx.beginPath();
ctx.arc(player.x, player.y, config.player.radius * 0.6, 0, Math.PI * 2);
ctx.fillStyle = 'white';
ctx.fill();
}
function drawBullets() {
bullets.forEach(bullet => {
// Glow effect
const glowIntensity = Math.abs(Math.sin(bullet.glow)) * 0.5 + 0.5;
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.radius * 1.5, 0, Math.PI * 2);
ctx.fillStyle = `${bullet.color}${Math.floor(glowIntensity * 30).toString(16).padStart(2, '0')}`;
ctx.fill();
// Bullet core
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.radius, 0, Math.PI * 2);
ctx.fillStyle = bullet.color;
ctx.shadowBlur = 10;
ctx.shadowColor = bullet.color;
ctx.fill();
ctx.shadowBlur = 0;
// Bullet center
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.radius * 0.5, 0, Math.PI * 2);
ctx.fillStyle = 'white';
ctx.fill();
});
}
function gameLoop() {
if (!isGameActive) return;
// Clear canvas with fade effect
ctx.fillStyle = 'rgba(18, 18, 48, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Spawn bullets
spawnCounter++;
const currentSpawnRate = Math.max(
config.bullets.minSpawnRate,
config.bullets.spawnRate - (difficultyLevel * config.bullets.spawnRateDecrease)
);
if (spawnCounter >= currentSpawnRate) {
spawnBullet();
spawnCounter = 0;
}
// Update game state
updatePlayer();
updateBullets();
increaseDifficulty();
// Draw game elements
drawBullets();
drawPlayer();
// Continue game loop
animationFrameId = requestAnimationFrame(gameLoop);
}
// Start the game when page loads
window.addEventListener('load', init);
</script>
</body>
</html>
I submitted the same prompt to Claude 4, and it came up with this result.
Now, Claude 4's results are also similar to Deepseek R1. It features a Neon theme, dynamic difficulty, displays the current level, and has a great UI. As for the code, Claude 4 wrote very good and clean code. It properly set the variables and divided the code into separate, easy-to-understand short functions.
In this case, it's too close to decide which one did better between Claude 4 and Deepseek R1 because both did a fantastic job creating this Dodgeball Game. Qwen 3 lagged a bit in this case.
Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bullet Dodging Game</title>
<style>
body {
margin: 0;
padding: 0;
background: #0a0a0a;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: 'Courier New', monospace;
color: #fff;
}
#gameContainer {
text-align: center;
background: #111;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 30px rgba(0, 255, 255, 0.3);
}
#gameCanvas {
border: 2px solid #00ffff;
background: #000;
box-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
}
#gameInfo {
margin-top: 15px;
display: flex;
justify-content: space-between;
font-size: 18px;
color: #00ffff;
}
#instructions {
margin-top: 10px;
font-size: 14px;
color: #aaa;
}
#gameOver {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 30px;
border-radius: 10px;
border: 2px solid #ff4444;
display: none;
text-align: center;
}
#restartBtn {
background: #00ffff;
color: #000;
border: none;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border-radius: 5px;
margin-top: 15px;
font-family: 'Courier New', monospace;
font-weight: bold;
}
#restartBtn:hover {
background: #44ffff;
}
</style>
</head>
<body>
<div id="gameContainer">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="gameInfo">
<div>Time: <span id="timeDisplay">0.0s</span></div>
<div>Level: <span id="levelDisplay">1</span></div>
<div>Score: <span id="scoreDisplay">0</span></div>
</div>
<div id="instructions">
Use WASD or Arrow Keys to move • Avoid all bullets • Survive as long as possible!
</div>
<div id="gameOver">
<h2 style="color: #ff4444; margin-top: 0;">GAME OVER</h2>
<p>Final Time: <span id="finalTime"></span></p>
<p>Final Score: <span id="finalScore"></span></p>
<button id="restartBtn">Play Again</button>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gameOverScreen = document.getElementById('gameOver');
// Game state
let gameRunning = false;
let gameTime = 0;
let score = 0;
let level = 1;
let lastTime = 0;
// Player
const player = {
x: canvas.width / 2,
y: canvas.height / 2,
size: 8,
speed: 4,
color: '#00ff00'
};
// Input handling
const keys = {};
// Bullets array
let bullets = [];
let nextBulletSpawn = 0;
// Event listeners
document.addEventListener('keydown', (e) => {
keys[e.code] = true;
});
document.addEventListener('keyup', (e) => {
keys[e.code] = false;
});
document.getElementById('restartBtn').addEventListener('click', startGame);
function startGame() {
gameRunning = true;
gameTime = 0;
score = 0;
level = 1;
player.x = canvas.width / 2;
player.y = canvas.height / 2;
bullets = [];
nextBulletSpawn = 0;
gameOverScreen.style.display = 'none';
gameLoop();
}
function updatePlayer(deltaTime) {
// Movement
let dx = 0, dy = 0;
if (keys['KeyA'] || keys['ArrowLeft']) dx -= player.speed;
if (keys['KeyD'] || keys['ArrowRight']) dx += player.speed;
if (keys['KeyW'] || keys['ArrowUp']) dy -= player.speed;
if (keys['KeyS'] || keys['ArrowDown']) dy += player.speed;
// Normalize diagonal movement
if (dx !== 0 && dy !== 0) {
dx *= 0.707;
dy *= 0.707;
}
// Update position with bounds checking
player.x = Math.max(player.size, Math.min(canvas.width - player.size, player.x + dx));
player.y = Math.max(player.size, Math.min(canvas.height - player.size, player.y + dy));
}
function spawnBullets(deltaTime) {
// Decrease spawn interval as difficulty increases
const baseSpawnInterval = Math.max(200, 800 - level * 80); // milliseconds
const spawnInterval = baseSpawnInterval + Math.random() * 400; // Add randomness
if (gameTime >= nextBulletSpawn) {
nextBulletSpawn = gameTime + spawnInterval;
// Number of bullets to spawn (increases with level)
const bulletsToSpawn = Math.min(1 + Math.floor(level / 3), 5);
for (let i = 0; i < bulletsToSpawn; i++) {
// Choose random side of screen
const side = Math.floor(Math.random() * 4);
let startX, startY, targetX, targetY;
switch (side) {
case 0: // Top
startX = Math.random() * canvas.width;
startY = -10;
break;
case 1: // Right
startX = canvas.width + 10;
startY = Math.random() * canvas.height;
break;
case 2: // Bottom
startX = Math.random() * canvas.width;
startY = canvas.height + 10;
break;
case 3: // Left
startX = -10;
startY = Math.random() * canvas.height;
break;
}
// Target can be anywhere on screen, with bias toward player
const playerBias = 0.7; // 70% chance to aim toward player area
if (Math.random() < playerBias) {
// Aim toward player area with some randomness
const randomRadius = 150;
targetX = player.x + (Math.random() - 0.5) * randomRadius;
targetY = player.y + (Math.random() - 0.5) * randomRadius;
} else {
// Completely random target
targetX = Math.random() * canvas.width;
targetY = Math.random() * canvas.height;
}
// Calculate direction
const dx = targetX - startX;
const dy = targetY - startY;
const distance = Math.sqrt(dx * dx + dy * dy);
// Random speed with level scaling
const speed = 1.5 + Math.random() * 2 + level * 0.2;
bullets.push({
x: startX,
y: startY,
vx: (dx / distance) * speed,
vy: (dy / distance) * speed,
size: 2 + Math.random() * 3, // Random bullet sizes
color: `hsl(${Math.random() * 360}, 80%, 60%)`, // Random colors
life: 0 // For potential fade effects
});
}
}
}
function updateBullets(deltaTime) {
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
bullet.x += bullet.vx;
bullet.y += bullet.vy;
bullet.life += deltaTime;
// Remove bullets that are off screen or too old
if (bullet.x < -100 || bullet.x > canvas.width + 100 ||
bullet.y < -100 || bullet.y > canvas.height + 100 ||
bullet.life > 15000) { // Remove after 15 seconds
bullets.splice(i, 1);
}
}
}
function checkCollisions() {
for (const bullet of bullets) {
const dx = player.x - bullet.x;
const dy = player.y - bullet.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < player.size + bullet.size) {
endGame();
return;
}
}
}
function updateGameState(deltaTime) {
gameTime += deltaTime;
score = Math.floor(gameTime / 10);
level = Math.floor(gameTime / 10000) + 1;
// Update display
document.getElementById('timeDisplay').textContent = (gameTime / 1000).toFixed(1) + 's';
document.getElementById('levelDisplay').textContent = level;
document.getElementById('scoreDisplay').textContent = score;
}
function render() {
// Clear canvas with fade effect
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw player
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.arc(player.x, player.y, player.size, 0, Math.PI * 2);
ctx.fill();
// Draw player glow
ctx.shadowBlur = 20;
ctx.shadowColor = player.color;
ctx.beginPath();
ctx.arc(player.x, player.y, player.size, 0, Math.PI * 2);
ctx.fill();
ctx.shadowBlur = 0;
// Draw bullets
bullets.forEach(bullet => {
ctx.fillStyle = bullet.color;
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.size, 0, Math.PI * 2);
ctx.fill();
// Bullet glow
ctx.shadowBlur = 10;
ctx.shadowColor = bullet.color;
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.size, 0, Math.PI * 2);
ctx.fill();
ctx.shadowBlur = 0;
});
}
function endGame() {
gameRunning = false;
document.getElementById('finalTime').textContent = (gameTime / 1000).toFixed(1) + 's';
document.getElementById('finalScore').textContent = score;
gameOverScreen.style.display = 'block';
}
function gameLoop(currentTime = 0) {
if (!gameRunning) return;
const deltaTime = currentTime - lastTime;
lastTime = currentTime;
updatePlayer(deltaTime);
spawnBullets(deltaTime);
updateBullets(deltaTime);
checkCollisions();
updateGameState(deltaTime);
render();
requestAnimationFrame(gameLoop);
}
// Start the game
startGame();
</script>
</body>
</html>
That's it for this blog. Claude 4, Deepseek R1, and Qwen 3 all did a great job, making it hard to choose between them. The best choice depends on what you need and the tasks you want to do. If you prefer detailed explanations and clear reasoning, Deepseek R1 is the way to go. If you want high-quality coding and the latest production-ready code, Claude 4 is a great option. Or if you need a flexible model that can turn incomplete ideas into working code, Qwen 3 is a good choice. It's ideal for solo developers, quick prototyping, and projects that combine logic, UI, and language.
Each model is strong in its own way, so choose the one that suits your needs best. Thanks for reading, and I’ll see you in the next blog!
Streamline your Engineering Team
Get started with a Free Trial or Book A Demo with the founderBuilding artificial
engineering intelligence.
Product
Home
Log In
Sign Up
Helpful Links
OSS Explore
PR Arena