pysolver33 commited on
Commit
9d095b4
Β·
verified Β·
1 Parent(s): 63b58c1

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +658 -16
index.html CHANGED
@@ -53,6 +53,55 @@
53
  from, to { border-color: transparent }
54
  50% { border-color: #a777e3; }
55
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  </style>
57
  </head>
58
  <body class="gradient-bg min-h-screen text-white">
@@ -131,7 +180,7 @@
131
  </div>
132
  </div>
133
 
134
- <div id="gameContainer" class="game-canvas w-full h-[500px] flex items-center justify-center">
135
  <div id="placeholderText" class="text-center p-8">
136
  <i class="fas fa-gamepad text-5xl mb-4 opacity-30"></i>
137
  <p class="text-xl opacity-50">Your AI-generated game will appear here</p>
@@ -209,6 +258,8 @@
209
  let currentGame = null;
210
  let selectedScaffold = null;
211
  let isSoundOn = true;
 
 
212
 
213
  // Initialize the app
214
  function init() {
@@ -377,22 +428,45 @@ const config = {
377
  },
378
  scene: {
379
  preload: function() {
380
- // Load assets here
 
 
 
 
 
381
  },
382
  create: function() {
383
- // Create player, platforms, enemies
384
- this.player = this.physics.add.sprite(100, 450, 'player');
385
- this.player.setCollideWorldBounds(true);
386
 
387
- // Generated platforms
388
  const platforms = this.physics.add.staticGroup();
389
  platforms.create(400, 568, 'ground').setScale(2).refreshBody();
390
 
 
 
 
 
 
391
  // Physics
392
  this.physics.add.collider(this.player, platforms);
 
 
 
393
  },
394
  update: function() {
395
- // Game loop
 
 
 
 
 
 
 
 
 
 
 
396
  }
397
  }
398
  };
@@ -401,7 +475,7 @@ const game = new Phaser.Game(config);`,
401
  rhythm: `// Rhythm game based on: "${prompt}"
402
  const synth = new Tone.Synth().toDestination();
403
  const notes = ['C4', 'D4', 'E4', 'F4', 'G4'];
404
- let currentNote = 0;
405
 
406
  function setupGame() {
407
  // Create note targets
@@ -411,14 +485,18 @@ function setupGame() {
411
  noteEl.className = 'note-target';
412
  noteEl.style.left = \`\${(i + 1) * 15}%\`;
413
  noteEl.dataset.note = note;
 
 
 
 
414
  container.appendChild(noteEl);
415
  });
416
 
417
  // Start music
418
  Tone.Transport.bpm.value = 120;
419
  Tone.Transport.scheduleRepeat(time => {
420
- synth.triggerAttackRelease(notes[currentNote], "8n", time);
421
- currentNote = (currentNote + 1) % notes.length;
422
  }, "8n");
423
 
424
  Tone.Transport.start();
@@ -426,7 +504,7 @@ function setupGame() {
426
  puzzle: `// Puzzle game based on: "${prompt}"
427
  class PuzzleGame {
428
  constructor() {
429
- this.gridSize = 8;
430
  this.pieces = [];
431
  this.selectedPiece = null;
432
 
@@ -450,20 +528,211 @@ class PuzzleGame {
450
  }
451
 
452
  render() {
453
- // Draw the puzzle board
454
  const container = document.getElementById('gameContainer');
455
  container.innerHTML = '';
456
 
457
  this.pieces.forEach(row => {
458
  row.forEach(piece => {
459
  const pieceEl = document.createElement('div');
460
- pieceEl.className = \`puzzle-piece type-\${piece.type}\`;
461
- pieceEl.dataset.x = piece.x;
462
- pieceEl.dataset.y = piece.y;
463
  container.appendChild(pieceEl);
464
  });
465
  });
466
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
467
  }`
468
  };
469
 
@@ -479,11 +748,16 @@ class PuzzleGame {
479
  } else if (typeof currentGame.cleanup === 'function') {
480
  currentGame.cleanup();
481
  }
 
 
 
 
482
  currentGame = null;
483
  }
484
 
485
  // Hide placeholder
486
  placeholderText.style.display = 'none';
 
487
 
488
  // Create game based on scaffold type
489
  switch (gameData.scaffold) {
@@ -496,8 +770,17 @@ class PuzzleGame {
496
  case 'puzzle':
497
  createPuzzleGame(gameData);
498
  break;
 
 
 
 
 
 
 
 
 
499
  default:
500
- // For other types, just show a placeholder
501
  placeholderText.style.display = 'block';
502
  placeholderText.innerHTML = `
503
  <i class="fas fa-gamepad text-5xl mb-4 opacity-30"></i>
@@ -764,6 +1047,353 @@ class PuzzleGame {
764
  };
765
  }
766
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
767
  // Update game controls based on game type
768
  function updateGameControls(gameType) {
769
  gameControls.innerHTML = '';
@@ -779,6 +1409,18 @@ class PuzzleGame {
779
  puzzle: [
780
  { label: 'Select', keys: 'Click', desc: 'Select pieces' }
781
  ],
 
 
 
 
 
 
 
 
 
 
 
 
782
  default: [
783
  { label: 'No controls', desc: 'This game type has no interactive controls' }
784
  ]
 
53
  from, to { border-color: transparent }
54
  50% { border-color: #a777e3; }
55
  }
56
+ .car {
57
+ position: absolute;
58
+ width: 50px;
59
+ height: 90px;
60
+ background-color: #3498db;
61
+ border-radius: 10px;
62
+ }
63
+ .opponent-car {
64
+ position: absolute;
65
+ width: 50px;
66
+ height: 90px;
67
+ background-color: #e74c3c;
68
+ border-radius: 10px;
69
+ }
70
+ .road {
71
+ position: absolute;
72
+ width: 100%;
73
+ height: 100%;
74
+ background-color: #34495e;
75
+ }
76
+ .lane-marker {
77
+ position: absolute;
78
+ width: 10px;
79
+ height: 60px;
80
+ background-color: #f1c40f;
81
+ }
82
+ .adventure-tile {
83
+ position: absolute;
84
+ width: 60px;
85
+ height: 60px;
86
+ background-color: #2ecc71;
87
+ border-radius: 5px;
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: center;
91
+ color: white;
92
+ font-weight: bold;
93
+ cursor: pointer;
94
+ transition: transform 0.2s;
95
+ }
96
+ .adventure-tile:hover {
97
+ transform: scale(1.05);
98
+ }
99
+ .npc {
100
+ background-color: #9b59b6;
101
+ }
102
+ .item {
103
+ background-color: #e67e22;
104
+ }
105
  </style>
106
  </head>
107
  <body class="gradient-bg min-h-screen text-white">
 
180
  </div>
181
  </div>
182
 
183
+ <div id="gameContainer" class="game-canvas w-full h-[500px] flex items-center justify-center relative overflow-hidden">
184
  <div id="placeholderText" class="text-center p-8">
185
  <i class="fas fa-gamepad text-5xl mb-4 opacity-30"></i>
186
  <p class="text-xl opacity-50">Your AI-generated game will appear here</p>
 
258
  let currentGame = null;
259
  let selectedScaffold = null;
260
  let isSoundOn = true;
261
+ let racingInterval = null;
262
+ let adventureState = null;
263
 
264
  // Initialize the app
265
  function init() {
 
428
  },
429
  scene: {
430
  preload: function() {
431
+ this.load.image('sky', 'assets/sky.png');
432
+ this.load.image('ground', 'assets/platform.png');
433
+ this.load.image('star', 'assets/star.png');
434
+ this.load.spritesheet('player', 'assets/player.png', {
435
+ frameWidth: 32, frameHeight: 48
436
+ });
437
  },
438
  create: function() {
439
+ // Create world
440
+ this.add.image(400, 300, 'sky');
 
441
 
442
+ // Platforms
443
  const platforms = this.physics.add.staticGroup();
444
  platforms.create(400, 568, 'ground').setScale(2).refreshBody();
445
 
446
+ // Player
447
+ this.player = this.physics.add.sprite(100, 450, 'player');
448
+ this.player.setBounce(0.2);
449
+ this.player.setCollideWorldBounds(true);
450
+
451
  // Physics
452
  this.physics.add.collider(this.player, platforms);
453
+
454
+ // Controls
455
+ this.cursors = this.input.keyboard.createCursorKeys();
456
  },
457
  update: function() {
458
+ // Movement logic
459
+ if (this.cursors.left.isDown) {
460
+ this.player.setVelocityX(-160);
461
+ } else if (this.cursors.right.isDown) {
462
+ this.player.setVelocityX(160);
463
+ } else {
464
+ this.player.setVelocityX(0);
465
+ }
466
+
467
+ if (this.cursors.up.isDown && this.player.body.touching.down) {
468
+ this.player.setVelocityY(-330);
469
+ }
470
  }
471
  }
472
  };
 
475
  rhythm: `// Rhythm game based on: "${prompt}"
476
  const synth = new Tone.Synth().toDestination();
477
  const notes = ['C4', 'D4', 'E4', 'F4', 'G4'];
478
+ let score = 0;
479
 
480
  function setupGame() {
481
  // Create note targets
 
485
  noteEl.className = 'note-target';
486
  noteEl.style.left = \`\${(i + 1) * 15}%\`;
487
  noteEl.dataset.note = note;
488
+ noteEl.addEventListener('click', () => {
489
+ synth.triggerAttackRelease(note, "8n");
490
+ score += 10;
491
+ });
492
  container.appendChild(noteEl);
493
  });
494
 
495
  // Start music
496
  Tone.Transport.bpm.value = 120;
497
  Tone.Transport.scheduleRepeat(time => {
498
+ const note = notes[Math.floor(Math.random() * notes.length)];
499
+ synth.triggerAttackRelease(note, "8n", time);
500
  }, "8n");
501
 
502
  Tone.Transport.start();
 
504
  puzzle: `// Puzzle game based on: "${prompt}"
505
  class PuzzleGame {
506
  constructor() {
507
+ this.gridSize = 4;
508
  this.pieces = [];
509
  this.selectedPiece = null;
510
 
 
528
  }
529
 
530
  render() {
 
531
  const container = document.getElementById('gameContainer');
532
  container.innerHTML = '';
533
 
534
  this.pieces.forEach(row => {
535
  row.forEach(piece => {
536
  const pieceEl = document.createElement('div');
537
+ pieceEl.className = 'puzzle-piece';
538
+ pieceEl.style.backgroundColor = \`hsl(\${Math.random() * 360}, 70%, 60%)\`;
539
+ pieceEl.addEventListener('click', () => this.handleClick(piece));
540
  container.appendChild(pieceEl);
541
  });
542
  });
543
  }
544
+
545
+ handleClick(piece) {
546
+ // Handle puzzle piece click
547
+ }
548
+ }`,
549
+ shooter: `// Shooter game based on: "${prompt}"
550
+ const config = {
551
+ type: Phaser.AUTO,
552
+ width: 800,
553
+ height: 600,
554
+ physics: {
555
+ default: 'arcade',
556
+ arcade: { debug: false }
557
+ },
558
+ scene: {
559
+ preload: function() {
560
+ this.load.image('player', 'assets/ship.png');
561
+ this.load.image('bullet', 'assets/bullet.png');
562
+ this.load.image('enemy', 'assets/enemy.png');
563
+ },
564
+ create: function() {
565
+ // Player
566
+ this.player = this.physics.add.sprite(400, 500, 'player');
567
+ this.player.setCollideWorldBounds(true);
568
+
569
+ // Bullets
570
+ this.bullets = this.physics.add.group();
571
+
572
+ // Enemies
573
+ this.enemies = this.physics.add.group();
574
+ this.time.addEvent({
575
+ delay: 1000,
576
+ callback: this.spawnEnemy,
577
+ callbackScope: this,
578
+ loop: true
579
+ });
580
+
581
+ // Controls
582
+ this.cursors = this.input.keyboard.createCursorKeys();
583
+ this.input.on('pointerdown', this.shoot, this);
584
+ },
585
+ update: function() {
586
+ // Movement
587
+ if (this.cursors.left.isDown) {
588
+ this.player.setVelocityX(-200);
589
+ } else if (this.cursors.right.isDown) {
590
+ this.player.setVelocityX(200);
591
+ } else {
592
+ this.player.setVelocityX(0);
593
+ }
594
+ },
595
+ shoot: function() {
596
+ const bullet = this.bullets.create(this.player.x, this.player.y, 'bullet');
597
+ bullet.setVelocityY(-300);
598
+ },
599
+ spawnEnemy: function() {
600
+ const x = Phaser.Math.Between(50, 750);
601
+ const enemy = this.enemies.create(x, 0, 'enemy');
602
+ enemy.setVelocityY(100);
603
+ }
604
+ }
605
+ };
606
+
607
+ const game = new Phaser.Game(config);`,
608
+ adventure: `// Adventure game based on: "${prompt}"
609
+ class AdventureGame {
610
+ constructor() {
611
+ this.worldSize = { width: 10, height: 10 };
612
+ this.playerPos = { x: 0, y: 0 };
613
+ this.npcs = [
614
+ { x: 3, y: 2, name: 'Wizard', dialog: 'Seek the magic orb!' },
615
+ { x: 7, y: 5, name: 'Merchant', dialog: 'I have potions for sale.' }
616
+ ];
617
+ this.items = [
618
+ { x: 5, y: 8, name: 'Magic Orb', description: 'Grants wishes' }
619
+ ];
620
+
621
+ this.renderWorld();
622
+ }
623
+
624
+ renderWorld() {
625
+ const container = document.getElementById('gameContainer');
626
+ container.innerHTML = '';
627
+
628
+ // Render tiles
629
+ for (let y = 0; y < this.worldSize.height; y++) {
630
+ for (let x = 0; x < this.worldSize.width; x++) {
631
+ const tile = document.createElement('div');
632
+ tile.className = 'adventure-tile';
633
+ tile.style.left = \`\${x * 7}%\`;
634
+ tile.style.top = \`\${y * 7}%\`;
635
+ container.appendChild(tile);
636
+ }
637
+ }
638
+
639
+ // Render NPCs
640
+ this.npcs.forEach(npc => {
641
+ const npcEl = document.createElement('div');
642
+ npcEl.className = 'adventure-tile npc';
643
+ npcEl.style.left = \`\${npc.x * 7}%\`;
644
+ npcEl.style.top = \`\${npc.y * 7}%\`;
645
+ npcEl.textContent = npc.name[0];
646
+ npcEl.title = npc.name;
647
+ container.appendChild(npcEl);
648
+ });
649
+
650
+ // Render items
651
+ this.items.forEach(item => {
652
+ const itemEl = document.createElement('div');
653
+ itemEl.className = 'adventure-tile item';
654
+ itemEl.style.left = \`\${item.x * 7}%\`;
655
+ itemEl.style.top = \`\${item.y * 7}%\`;
656
+ itemEl.textContent = item.name[0];
657
+ itemEl.title = item.name;
658
+ container.appendChild(itemEl);
659
+ });
660
+ }
661
+ }`,
662
+ racing: `// Racing game based on: "${prompt}"
663
+ class RacingGame {
664
+ constructor() {
665
+ this.playerCar = { x: 50, y: 400, speed: 0 };
666
+ this.opponents = [
667
+ { x: 150, y: 100, speed: 3 },
668
+ { x: 250, y: 0, speed: 4 },
669
+ { x: 350, y: -100, speed: 3.5 }
670
+ ];
671
+ this.road = [];
672
+
673
+ this.initGame();
674
+ this.startRace();
675
+ }
676
+
677
+ initGame() {
678
+ const container = document.getElementById('gameContainer');
679
+ container.innerHTML = '';
680
+
681
+ // Create road
682
+ for (let i = 0; i < 20; i++) {
683
+ const marker = document.createElement('div');
684
+ marker.className = 'lane-marker';
685
+ marker.style.left = '45%';
686
+ marker.style.top = \`\${i * 120}px\`;
687
+ container.appendChild(marker);
688
+ }
689
+
690
+ // Create player car
691
+ const car = document.createElement('div');
692
+ car.className = 'car';
693
+ car.style.left = \`\${this.playerCar.x}px\`;
694
+ car.style.top = \`\${this.playerCar.y}px\`;
695
+ container.appendChild(car);
696
+
697
+ // Create opponent cars
698
+ this.opponents.forEach(opp => {
699
+ const oppCar = document.createElement('div');
700
+ oppCar.className = 'opponent-car';
701
+ oppCar.style.left = \`\${opp.x}px\`;
702
+ oppCar.style.top = \`\${opp.y}px\`;
703
+ container.appendChild(oppCar);
704
+ });
705
+ }
706
+
707
+ startRace() {
708
+ // Handle keyboard controls
709
+ document.addEventListener('keydown', (e) => {
710
+ if (e.key === 'ArrowLeft') this.playerCar.x = Math.max(50, this.playerCar.x - 20);
711
+ if (e.key === 'ArrowRight') this.playerCar.x = Math.min(350, this.playerCar.x + 20);
712
+ if (e.key === 'ArrowUp') this.playerCar.speed = Math.min(10, this.playerCar.speed + 0.5);
713
+ if (e.key === 'ArrowDown') this.playerCar.speed = Math.max(0, this.playerCar.speed - 0.5);
714
+
715
+ // Update player car position
716
+ document.querySelector('.car').style.left = \`\${this.playerCar.x}px\`;
717
+ });
718
+
719
+ // Game loop
720
+ setInterval(() => {
721
+ // Move opponents
722
+ this.opponents.forEach(opp => {
723
+ opp.y += opp.speed;
724
+ if (opp.y > 600) opp.y = -100;
725
+ document.querySelectorAll('.opponent-car')[this.opponents.indexOf(opp)].style.top = \`\${opp.y}px\`;
726
+ });
727
+
728
+ // Move road markers
729
+ const markers = document.querySelectorAll('.lane-marker');
730
+ markers.forEach(marker => {
731
+ const currentTop = parseInt(marker.style.top);
732
+ marker.style.top = \`\${(currentTop + this.playerCar.speed) % 600}px\`;
733
+ });
734
+ }, 16);
735
+ }
736
  }`
737
  };
738
 
 
748
  } else if (typeof currentGame.cleanup === 'function') {
749
  currentGame.cleanup();
750
  }
751
+ if (racingInterval) {
752
+ clearInterval(racingInterval);
753
+ racingInterval = null;
754
+ }
755
  currentGame = null;
756
  }
757
 
758
  // Hide placeholder
759
  placeholderText.style.display = 'none';
760
+ gameContainer.innerHTML = '';
761
 
762
  // Create game based on scaffold type
763
  switch (gameData.scaffold) {
 
770
  case 'puzzle':
771
  createPuzzleGame(gameData);
772
  break;
773
+ case 'shooter':
774
+ createShooterGame(gameData);
775
+ break;
776
+ case 'adventure':
777
+ createAdventureGame(gameData);
778
+ break;
779
+ case 'racing':
780
+ createRacingGame(gameData);
781
+ break;
782
  default:
783
+ // Fallback
784
  placeholderText.style.display = 'block';
785
  placeholderText.innerHTML = `
786
  <i class="fas fa-gamepad text-5xl mb-4 opacity-30"></i>
 
1047
  };
1048
  }
1049
 
1050
+ // Create a shooter game
1051
+ function createShooterGame(gameData) {
1052
+ const config = {
1053
+ type: Phaser.AUTO,
1054
+ width: gameContainer.clientWidth,
1055
+ height: gameContainer.clientHeight,
1056
+ physics: {
1057
+ default: 'arcade',
1058
+ arcade: {
1059
+ debug: false
1060
+ }
1061
+ },
1062
+ parent: 'gameContainer',
1063
+ scene: {
1064
+ preload: preload,
1065
+ create: create,
1066
+ update: update
1067
+ }
1068
+ };
1069
+
1070
+ currentGame = new Phaser.Game(config);
1071
+
1072
+ function preload() {
1073
+ // Load assets
1074
+ this.load.image('ship', 'https://labs.phaser.io/assets/sprites/thrust_ship2.png');
1075
+ this.load.image('bullet', 'https://labs.phaser.io/assets/sprites/bullets/bullet6.png');
1076
+ this.load.image('enemy', 'https://labs.phaser.io/assets/sprites/asteroid.png');
1077
+ }
1078
+
1079
+ function create() {
1080
+ // Add background
1081
+ this.add.rectangle(0, 0, config.width, config.height, 0x1a1a2e).setOrigin(0);
1082
+
1083
+ // Player
1084
+ this.player = this.physics.add.sprite(config.width / 2, config.height - 50, 'ship');
1085
+ this.player.setCollideWorldBounds(true);
1086
+
1087
+ // Bullets
1088
+ this.bullets = this.physics.add.group();
1089
+
1090
+ // Enemies
1091
+ this.enemies = this.physics.add.group();
1092
+ this.time.addEvent({
1093
+ delay: 1000,
1094
+ callback: spawnEnemy,
1095
+ callbackScope: this,
1096
+ loop: true
1097
+ });
1098
+
1099
+ // Controls
1100
+ this.cursors = this.input.keyboard.createCursorKeys();
1101
+ this.input.on('pointerdown', shoot, this);
1102
+
1103
+ // Score
1104
+ this.score = 0;
1105
+ this.scoreText = this.add.text(16, 16, 'Score: 0', {
1106
+ fontSize: '24px',
1107
+ fill: '#fff',
1108
+ fontFamily: 'Arial'
1109
+ });
1110
+
1111
+ function shoot() {
1112
+ const bullet = this.bullets.create(this.player.x, this.player.y - 20, 'bullet');
1113
+ bullet.setVelocityY(-300);
1114
+
1115
+ if (isSoundOn) {
1116
+ const synth = new Tone.Synth().toDestination();
1117
+ synth.triggerAttackRelease("A2", "8n");
1118
+ }
1119
+ }
1120
+
1121
+ function spawnEnemy() {
1122
+ const x = Phaser.Math.Between(50, config.width - 50);
1123
+ const enemy = this.enemies.create(x, 0, 'enemy');
1124
+ enemy.setScale(0.5);
1125
+ enemy.setVelocityY(Phaser.Math.Between(50, 150));
1126
+
1127
+ // Collision
1128
+ this.physics.add.collider(this.bullets, this.enemies, hitEnemy, null, this);
1129
+
1130
+ function hitEnemy(bullet, enemy) {
1131
+ bullet.destroy();
1132
+ enemy.destroy();
1133
+
1134
+ this.score += 10;
1135
+ this.scoreText.setText('Score: ' + this.score);
1136
+
1137
+ if (isSoundOn) {
1138
+ const synth = new Tone.Synth().toDestination();
1139
+ synth.triggerAttackRelease("C5", "8n");
1140
+ }
1141
+ }
1142
+ }
1143
+ }
1144
+
1145
+ function update() {
1146
+ // Movement
1147
+ if (this.cursors.left.isDown) {
1148
+ this.player.setVelocityX(-200);
1149
+ } else if (this.cursors.right.isDown) {
1150
+ this.player.setVelocityX(200);
1151
+ } else {
1152
+ this.player.setVelocityX(0);
1153
+ }
1154
+ }
1155
+ }
1156
+
1157
+ // Create an adventure game
1158
+ function createAdventureGame(gameData) {
1159
+ // Clear container
1160
+ gameContainer.innerHTML = '';
1161
+
1162
+ // Game state
1163
+ adventureState = {
1164
+ playerPos: { x: 0, y: 0 },
1165
+ inventory: [],
1166
+ npcs: [
1167
+ { x: 3, y: 2, name: 'Wizard', dialog: 'Seek the magic orb to win the game!' },
1168
+ { x: 7, y: 5, name: 'Merchant', dialog: 'I have potions for sale. (Coming soon!)' }
1169
+ ],
1170
+ items: [
1171
+ { x: 5, y: 8, name: 'Magic Orb', description: 'The legendary orb that grants wishes' }
1172
+ ]
1173
+ };
1174
+
1175
+ // Render world
1176
+ renderAdventureWorld();
1177
+
1178
+ currentGame = {
1179
+ cleanup: () => {
1180
+ adventureState = null;
1181
+ }
1182
+ };
1183
+
1184
+ function renderAdventureWorld() {
1185
+ // Clear container
1186
+ gameContainer.innerHTML = '';
1187
+
1188
+ // Create grid
1189
+ const gridSize = 10;
1190
+ const tileSize = Math.min(
1191
+ gameContainer.clientWidth / gridSize - 2,
1192
+ gameContainer.clientHeight / gridSize - 2
1193
+ );
1194
+
1195
+ // Render tiles
1196
+ for (let y = 0; y < gridSize; y++) {
1197
+ for (let x = 0; x < gridSize; x++) {
1198
+ const tile = document.createElement('div');
1199
+ tile.className = 'adventure-tile';
1200
+ tile.style.width = `${tileSize}px`;
1201
+ tile.style.height = `${tileSize}px`;
1202
+ tile.style.left = `${x * (tileSize + 2)}px`;
1203
+ tile.style.top = `${y * (tileSize + 2)}px`;
1204
+
1205
+ // Mark player position
1206
+ if (x === adventureState.playerPos.x && y === adventureState.playerPos.y) {
1207
+ tile.innerHTML = '<i class="fas fa-user"></i>';
1208
+ tile.style.backgroundColor = '#3498db';
1209
+ }
1210
+
1211
+ gameContainer.appendChild(tile);
1212
+ }
1213
+ }
1214
+
1215
+ // Render NPCs
1216
+ adventureState.npcs.forEach(npc => {
1217
+ const npcEl = document.createElement('div');
1218
+ npcEl.className = 'adventure-tile npc';
1219
+ npcEl.style.width = `${tileSize}px`;
1220
+ npcEl.style.height = `${tileSize}px`;
1221
+ npcEl.style.left = `${npc.x * (tileSize + 2)}px`;
1222
+ npcEl.style.top = `${npc.y * (tileSize + 2)}px`;
1223
+ npcEl.innerHTML = `<i class="fas fa-hat-wizard"></i>`;
1224
+ npcEl.title = npc.name;
1225
+
1226
+ npcEl.addEventListener('click', () => {
1227
+ alert(`${npc.name}: ${npc.dialog}`);
1228
+ });
1229
+
1230
+ gameContainer.appendChild(npcEl);
1231
+ });
1232
+
1233
+ // Render items
1234
+ adventureState.items.forEach(item => {
1235
+ const itemEl = document.createElement('div');
1236
+ itemEl.className = 'adventure-tile item';
1237
+ itemEl.style.width = `${tileSize}px`;
1238
+ itemEl.style.height = `${tileSize}px`;
1239
+ itemEl.style.left = `${item.x * (tileSize + 2)}px`;
1240
+ itemEl.style.top = `${item.y * (tileSize + 2)}px`;
1241
+ itemEl.innerHTML = `<i class="fas fa-gem"></i>`;
1242
+ itemEl.title = item.name;
1243
+
1244
+ itemEl.addEventListener('click', () => {
1245
+ if (Math.abs(adventureState.playerPos.x - item.x) <= 1 &&
1246
+ Math.abs(adventureState.playerPos.y - item.y) <= 1) {
1247
+ alert(`You found the ${item.name}! ${item.description}`);
1248
+ adventureState.items = adventureState.items.filter(i => i !== item);
1249
+ renderAdventureWorld();
1250
+ } else {
1251
+ alert(`You need to get closer to the ${item.name}!`);
1252
+ }
1253
+ });
1254
+
1255
+ gameContainer.appendChild(itemEl);
1256
+ });
1257
+
1258
+ // Add controls
1259
+ document.addEventListener('keydown', (e) => {
1260
+ const newPos = {...adventureState.playerPos};
1261
+
1262
+ switch(e.key) {
1263
+ case 'ArrowUp':
1264
+ newPos.y = Math.max(0, adventureState.playerPos.y - 1);
1265
+ break;
1266
+ case 'ArrowDown':
1267
+ newPos.y = Math.min(gridSize - 1, adventureState.playerPos.y + 1);
1268
+ break;
1269
+ case 'ArrowLeft':
1270
+ newPos.x = Math.max(0, adventureState.playerPos.x - 1);
1271
+ break;
1272
+ case 'ArrowRight':
1273
+ newPos.x = Math.min(gridSize - 1, adventureState.playerPos.x + 1);
1274
+ break;
1275
+ }
1276
+
1277
+ if (newPos.x !== adventureState.playerPos.x || newPos.y !== adventureState.playerPos.y) {
1278
+ adventureState.playerPos = newPos;
1279
+ renderAdventureWorld();
1280
+ }
1281
+ });
1282
+ }
1283
+ }
1284
+
1285
+ // Create a racing game
1286
+ function createRacingGame(gameData) {
1287
+ // Clear container
1288
+ gameContainer.innerHTML = '';
1289
+
1290
+ // Game state
1291
+ const state = {
1292
+ player: { x: 175, y: 400, speed: 0, maxSpeed: 10 },
1293
+ opponents: [
1294
+ { x: 75, y: -100, speed: 3 },
1295
+ { x: 175, y: -300, speed: 4 },
1296
+ { x: 275, y: -500, speed: 3.5 }
1297
+ ],
1298
+ roadMarkers: Array.from({ length: 20 }, (_, i) => ({ y: i * 120 })),
1299
+ score: 0
1300
+ };
1301
+
1302
+ // Create road
1303
+ const road = document.createElement('div');
1304
+ road.className = 'road';
1305
+ gameContainer.appendChild(road);
1306
+
1307
+ // Create road markers
1308
+ state.roadMarkers.forEach(marker => {
1309
+ const markerEl = document.createElement('div');
1310
+ markerEl.className = 'lane-marker';
1311
+ markerEl.style.left = '45%';
1312
+ markerEl.style.top = `${marker.y}px`;
1313
+ gameContainer.appendChild(markerEl);
1314
+ });
1315
+
1316
+ // Create player car
1317
+ const playerCar = document.createElement('div');
1318
+ playerCar.className = 'car';
1319
+ playerCar.style.left = `${state.player.x}px`;
1320
+ playerCar.style.top = `${state.player.y}px`;
1321
+ gameContainer.appendChild(playerCar);
1322
+
1323
+ // Create opponent cars
1324
+ state.opponents.forEach(opp => {
1325
+ const oppCar = document.createElement('div');
1326
+ oppCar.className = 'opponent-car';
1327
+ oppCar.style.left = `${opp.x}px`;
1328
+ oppCar.style.top = `${opp.y}px`;
1329
+ gameContainer.appendChild(oppCar);
1330
+ });
1331
+
1332
+ // Score display
1333
+ const scoreEl = document.createElement('div');
1334
+ scoreEl.className = 'absolute top-4 left-4 text-white font-bold text-xl';
1335
+ scoreEl.textContent = `Score: ${state.score}`;
1336
+ gameContainer.appendChild(scoreEl);
1337
+
1338
+ // Controls
1339
+ document.addEventListener('keydown', (e) => {
1340
+ if (e.key === 'ArrowLeft') state.player.x = Math.max(75, state.player.x - 100);
1341
+ if (e.key === 'ArrowRight') state.player.x = Math.min(275, state.player.x + 100);
1342
+ if (e.key === 'ArrowUp') state.player.speed = Math.min(state.player.maxSpeed, state.player.speed + 0.5);
1343
+ if (e.key === 'ArrowDown') state.player.speed = Math.max(0, state.player.speed - 0.5);
1344
+
1345
+ // Update player car position
1346
+ playerCar.style.left = `${state.player.x}px`;
1347
+ });
1348
+
1349
+ // Game loop
1350
+ racingInterval = setInterval(() => {
1351
+ // Move opponents
1352
+ state.opponents.forEach(opp => {
1353
+ opp.y += opp.speed;
1354
+ if (opp.y > gameContainer.clientHeight) {
1355
+ opp.y = -100;
1356
+ state.score += 10;
1357
+ scoreEl.textContent = `Score: ${state.score}`;
1358
+ }
1359
+
1360
+ // Check collision
1361
+ if (Math.abs(opp.x - state.player.x) < 50 &&
1362
+ Math.abs(opp.y - state.player.y) < 50) {
1363
+ state.player.speed = Math.max(0, state.player.speed - 1);
1364
+ }
1365
+
1366
+ // Update opponent position
1367
+ document.querySelectorAll('.opponent-car')[state.opponents.indexOf(opp)].style.top = `${opp.y}px`;
1368
+ });
1369
+
1370
+ // Move road markers
1371
+ state.roadMarkers.forEach(marker => {
1372
+ marker.y += state.player.speed;
1373
+ if (marker.y > gameContainer.clientHeight) {
1374
+ marker.y = 0;
1375
+ }
1376
+
1377
+ // Update marker position
1378
+ const markers = document.querySelectorAll('.lane-marker');
1379
+ markers[state.roadMarkers.indexOf(marker)].style.top = `${marker.y}px`;
1380
+ });
1381
+
1382
+ // Update score based on speed
1383
+ state.score += Math.floor(state.player.speed / 10);
1384
+ scoreEl.textContent = `Score: ${state.score}`;
1385
+ }, 16);
1386
+
1387
+ currentGame = {
1388
+ cleanup: () => {
1389
+ if (racingInterval) {
1390
+ clearInterval(racingInterval);
1391
+ racingInterval = null;
1392
+ }
1393
+ }
1394
+ };
1395
+ }
1396
+
1397
  // Update game controls based on game type
1398
  function updateGameControls(gameType) {
1399
  gameControls.innerHTML = '';
 
1409
  puzzle: [
1410
  { label: 'Select', keys: 'Click', desc: 'Select pieces' }
1411
  ],
1412
+ shooter: [
1413
+ { label: 'Left/Right', keys: '← β†’', desc: 'Move ship' },
1414
+ { label: 'Shoot', keys: 'Click', desc: 'Fire bullets' }
1415
+ ],
1416
+ adventure: [
1417
+ { label: 'Move', keys: 'Arrow Keys', desc: 'Navigate the world' },
1418
+ { label: 'Interact', keys: 'Click', desc: 'Talk to NPCs or collect items' }
1419
+ ],
1420
+ racing: [
1421
+ { label: 'Left/Right', keys: '← β†’', desc: 'Change lanes' },
1422
+ { label: 'Accelerate/Brake', keys: '↑ ↓', desc: 'Control speed' }
1423
+ ],
1424
  default: [
1425
  { label: 'No controls', desc: 'This game type has no interactive controls' }
1426
  ]