FIRST INSTALL
一、deepseek本地模型 下载
* 1.1 ollama下载
https://ollama.com/download
* 1.2 deepseek-r1 下载
export OLLAMA_HOST=0.0.0.0:11434
ollama run deepseek-r1:7b
* 1.3 pageassisnt chrome 插件安装
* 1.4 本地访问ollama服务
cmd
curl -X POST http://localhost:11434/api/generate \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-r1:7b", "prompt": "What is the capital of France?", "stream": false }'
node js - app.post('/generate', async (req, res) => {
- const { prompt } = req.body;
- var model="deepseek-r1:7b"
- var stream=false
- console.log({
- model: model,
- prompt: prompt,
- stream: stream
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- try {
- const response = await axios.post('http://localhost:11434/api/generate', {
- model: model,
- prompt: prompt,
- stream: stream
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- });
- console.log(response)
- res.send(response.data.response);
- } catch (error) {
- console.error('Error accessing deepseekr1 model:', error);
- res.status(500).send('Internal Server Error');
- }
- });
复制代码
二、游戏下载
1、phaser
cnpm install phaser axios body-parse express http
node server2.js
- const express = require('express');
- const axios = require('axios');
- const bodyParser = require('body-parser');
- const path = require('path');
- const app = express();
- const PORT = 3000; // 你可以根据需要更改端口
- app.use(bodyParser.json());
- app.use(bodyParser.json());
- app.use(bodyParser.urlencoded({ extended: true }));
- // 设置public文件夹为静态文件目录
- app.use(express.static(path.join(__dirname, 'public')));
- app.post('/generatejson', async (req, res) => {
- const { prompt } = req.body;
- var model="deepseek-r1:7b"
- var stream=false
- console.log({
- model: model,
- prompt: prompt,
- stream: stream
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- try {
- const response = await axios.post('http://localhost:11434/api/generate', {
- model: model,
- prompt: prompt,
- stream: stream
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- });
- console.log(response)
- res.send(response.data);
- } catch (error) {
- console.error('Error accessing deepseekr1 model:', error);
- res.status(500).send('Internal Server Error');
- }
- });
- app.post('/generate', async (req, res) => {
- const { prompt } = req.body;
- var model="deepseek-r1:7b"
- var stream=false
- console.log({
- model: model,
- prompt: prompt,
- stream: stream
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- try {
- const response = await axios.post('http://localhost:11434/api/generate', {
- model: model,
- prompt: prompt,
- stream: stream
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- });
- console.log(response)
- res.send(response.data.response);
- } catch (error) {
- console.error('Error accessing deepseekr1 model:', error);
- res.status(500).send('Internal Server Error');
- }
- });
- app.listen(PORT, () => {
- console.log(`Server is running on http://localhost:${PORT}`);
- });
复制代码
2、游戏案例
- <!doctype html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <title>Making your first Phaser 3 Game - Part 10</title>
- <script src="lib/phaser.min.js"></script>
- <style type="text/css">
- body {
- margin: 0;
- }
- #game-container {
- position: relative;
- }
- #input-container {
- position: absolute;
- bottom: 10px;
- width: 100%;
- text-align: center;
- }
- #input-box {
- padding: 10px;
- font-size: 16px;
- width: 300px;
- }
- #send-button {
- padding: 10px;
- font-size: 16px;
- }
- #npc-selector {
- padding: 10px;
- font-size: 16px;
- margin-right: 10px;
- }
- </style>
- </head>
- <body>
- <div id="game-container">
- </div>
- <div id="input-container">
- <select id="npc-selector">
- <option value="greengirl">Green Girl</option>
- <option value="bluegirl">Blue Girl</option>
- <option value="yellowman">Yellow Man</option>
- </select>
- <input type="text" id="input-box" placeholder="Type your message here...">
- <button id="send-button">Send</button>
- </div>
- <script type="text/javascript">
- var config = {
- type: Phaser.AUTO,
- width: 1000,
- height: 600,
- physics: {
- default: 'arcade',
- arcade: {
- gravity: { y: 300 },
- debug: false
- }
- },
- scene: {
- preload: preload,
- create: create,
- update: update
- }
- };
- var player;
- var npc; // NPC character
- var stars;
- var bombs;
- var platforms;
- var cursors;
- var playerScore = 0;
- var npcScore = 16;
- var gameOver = false;
- var scoreText;
- var npcScoreText;
- var dialogueBox;
- var dialogueText;
- var npcDialogueBox;
- var npcDialogueText;
- var isWaitingResponse = false;
- var npcIsWaitingResponse = false;
- var playerHitBomb = false;
- var npcHitBomb = false;
- var npcSkin='greengirl';
- var game = new Phaser.Game(config);
- function preload () {
- this.load.image('sky', 'assets/sky.png');
- this.load.image('ground', 'assets/platform.png');
- this.load.image('star', 'assets/star.png');
- this.load.image('bomb', 'assets/bomb.png');
- this.load.spritesheet('dude', 'assets/dude.png', { frameWidth: 32, frameHeight: 48 });
- this.load.spritesheet('greengirl', 'assets/greengirl.png', { frameWidth: 32, frameHeight: 48 });
- this.load.spritesheet('bluegirl', 'assets/bluegirl.png', { frameWidth: 32, frameHeight: 48 });
- this.load.spritesheet('yellowman', 'assets/yellowman.png', { frameWidth: 32, frameHeight: 48 });
- }
- function create () {
- // A simple background for our game
- this.add.image(400, 300, 'sky');
- // The platforms group contains the ground and the 2 ledges we can jump on
- platforms = this.physics.add.staticGroup();
- // Here we create the ground.
- // Scale it to fit the width of the game (the original sprite is 400x32 in size)
- platforms.create(400, 568, 'ground').setScale(2).refreshBody();
- // Now let's create some ledges
- platforms.create(600, 400, 'ground');
- platforms.create(50, 250, 'ground');
- platforms.create(750, 220, 'ground');
- // The player and its settings
- player = this.physics.add.sprite(100, 450, 'dude');
- player.setBounce(0.2);
- player.setCollideWorldBounds(true);
- // Our player animations, turning, walking left and walking right.
- this.anims.create({
- key: 'left',
- frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
- frameRate: 10,
- repeat: -1
- });
- this.anims.create({
- key: 'turn',
- frames: [ { key: 'dude', frame: 4 }],
- frameRate: 20
- });
- this.anims.create({
- key: 'right',
- frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
- frameRate: 10,
- repeat: -1
- });
- // Create NPC
- npc = this.physics.add.sprite(700, 450, 'greengirl');
- npc.setBounce(0.2);
- npc.setCollideWorldBounds(true);
- var npcSkins = ['greengirl', 'bluegirl', 'yellowman'];
- npcSkins.forEach(snpcSkin => {
- this.anims.create({
- key: snpcSkin + 'left',
- frames: this.anims.generateFrameNumbers(snpcSkin, { start: 4, end: 7 }),
- frameRate: 10,
- repeat: -1
- });
- this.anims.create({
- key: snpcSkin + 'turn',
- frames: [ { key: snpcSkin, frame: 0 }],
- frameRate: 20
- });
- this.anims.create({
- key: snpcSkin + 'right',
- frames: this.anims.generateFrameNumbers(snpcSkin, { start: 8, end: 11 }),
- frameRate: 10,
- repeat: -1
- });
- });
- // Input Events
- cursors = this.input.keyboard.createCursorKeys();
- // Some stars to collect, 12 in total, evenly spaced 70 pixels apart along the x axis
- stars = this.physics.add.group({
- key: 'star',
- repeat: 11,
- setXY: { x: 12, y: 0, stepX: 70 }
- });
- stars.children.iterate(function (child) {
- child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
- });
- bombs = this.physics.add.group();
- // The score
- scoreText = this.add.text(16, 16, 'Player Score: 0', { fontSize: '32px', fill: '#000' });
- npcScoreText = this.add.text(400, 16, 'NPC Score: 0', { fontSize: '32px', fill: '#000' });
- // Collide the player and the stars with the platforms
- this.physics.add.collider(player, platforms);
- this.physics.add.collider(stars, platforms);
- this.physics.add.collider(bombs, platforms);
- // Checks to see if the player overlaps with any of the stars, if he does call the collectStar function
- this.physics.add.overlap(player, stars, collectStar, null, this);
- // Create dialogue box (hidden initially)
- dialogueBox = this.add.rectangle(player.x, player.y - 50, 200, 50, 0x000000, 0.8);
- dialogueBox.visible = false;
- // Create dialogue text
- dialogueText = this.add.text(player.x, player.y - 50, '', { font: '16px Arial', fill: '#ffffff', align: 'center' });
- dialogueText.setOrigin(0.5, 0.5);
- dialogueText.visible = false;
- // Create NPC dialogue box (hidden initially)
- npcDialogueBox = this.add.rectangle(npc.x, npc.y - 50, 200, 50, 0x000000, 0.8);
- npcDialogueBox.visible = false;
- // Create NPC dialogue text
- npcDialogueText = this.add.text(npc.x, npc.y - 50, '', { font: '16px Arial', fill: '#ffffff', align: 'center' });
- npcDialogueText.setOrigin(0.5, 0.5);
- npcDialogueText.visible = false;
- // Add event listener to the send button
- document.getElementById('send-button').addEventListener('click', sendDialogue);
- // Add event listener to the input box for Enter key
- document.getElementById('input-box').addEventListener('keypress', function(event) {
- if (event.key === 'Enter') {
- sendDialogue();
- }
- });
- this.physics.add.collider(npc, platforms);
- // NPC collects stars
- this.physics.add.overlap(npc, stars, npcCollectStar, null, this);
- this.physics.add.collider(player, bombs, hitBomb, null, this);
- this.physics.add.collider(npc, bombs, hitBomb, null, this);
- // Add event listener to NPC selector
- document.getElementById('npc-selector').addEventListener('change', changeNPC);
- // Add collision between player and NPC
- this.physics.add.collider(player, npc, onCollide, null, this);
- }
- function update () {
- if (gameOver) {
- return;
- }
- if (!playerHitBomb) {
- if (cursors.left.isDown) {
- player.setVelocityX(-160);
- player.anims.play('left', true);
- } else if (cursors.right.isDown) {
- player.setVelocityX(160);
- player.anims.play('right', true);
- } else {
- player.setVelocityX(0);
- player.anims.play('turn');
- }
- if (cursors.up.isDown && player.body.touching.down) {
- player.setVelocityY(-330);
- }
- if (cursors.down.isDown) {
- player.setVelocityY(600); // Accelerate downward movement when 'S' key is pressed
- }
- }
- if (!npcHitBomb) {
- // NPC movement using ASWD keys
- if (this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A).isDown) {
- npc.setVelocityX(-160);
- npc.anims.play(npcSkin+'left', true);
- } else if (this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D).isDown) {
- npc.setVelocityX(160);
- npc.anims.play(npcSkin+'right', true);
- } else {
- npc.setVelocityX(0);
- npc.anims.play(npcSkin+'turn');
- }
- if (this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W).isDown && npc.body.touching.down) {
- npc.setVelocityY(-330);
- if (!npcIsWaitingResponse) {
- fetchJoke();
- }
- }
- if (this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S).isDown) {
- npc.setVelocityY(600); // Accelerate downward movement when 'S' key is pressed
- }
- }
- // Update dialogue box position based on player position
- dialogueBox.x = player.x;
- dialogueText.x = player.x;
- dialogueBox.y = player.y-50;
- dialogueText.y = player.y-50;
- // Update NPC dialogue box position based on NPC position
- npcDialogueBox.x = npc.x;
- npcDialogueText.x = npc.x;
- npcDialogueBox.y = npc.y-50;
- npcDialogueText.y = npc.y-50;
- }
- function collectStar (player, star) {
- star.disableBody(true, true);
- playerScore += 10;
- scoreText.setText('Player Score: ' + playerScore);
- if (stars.countActive(true) === 0) {
- stars.children.iterate(function (child) {
- child.enableBody(true, child.x, 0, true, true);
- });
- var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
- var bomb = bombs.create(x, 16, 'bomb');
- bomb.setBounce(1);
- bomb.setCollideWorldBounds(true);
- bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
- bomb.allowGravity = false;
- }
- }
- function npcCollectStar (npc, star) {
- star.disableBody(true, true);
- npcScore += 10;
- npcScoreText.setText('NPC Score: ' + npcScore);
- if (stars.countActive(true) === 0) {
- stars.children.iterate(function (child) {
- child.enableBody(true, child.x, 0, true, true);
- });
- var x = (npc.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
- var bomb = bombs.create(x, 16, 'bomb');
- bomb.setBounce(1);
- bomb.setCollideWorldBounds(true);
- bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
- bomb.allowGravity = false;
- }
- }
- function hitBomb (character, bomb) {
- if (character === player) {
- playerHitBomb = true;
- character.setVelocity(0);
- character.setTint(0xff0000);
- character.anims.play('turn');
- } else {
- npcHitBomb = true;
- character.setVelocity(0);
- character.setTint(0xff0000);
- character.anims.play(npcSkin+'turn');
- }
- if (playerHitBomb && npcHitBomb) {
- gameOver = true;
- this.physics.pause();
- }
- }
- function onCollide (player, npc) {
- // Calculate the angle of collision
- var angle = Phaser.Math.Angle.Between(player.x, player.y, npc.x, npc.y);
- // Calculate the force vector
- var force = 100; // Increase force for stronger hit
- var fx = Math.cos(angle) * force;
- var fy = Math.sin(angle) * force;
- // Apply the force to both characters
- player.setVelocityX(player.x -100 );
- player.setVelocityY(player.y + 10);
- npc.setVelocityX(npc.x +100);
- npc.setVelocityY(npc.y - 10 );
- // Play hit animation
- player.anims.play('turn');
- npc.anims.play(npcSkin+'turn');
- }
- function sendDialogue() {
- if (isWaitingResponse) return;
- const inputBox = document.getElementById('input-box');
- const message = inputBox.value.trim();
- dialogueBox.visible = false;
- dialogueText.visible = false;
- if (message === '') return;
- dialogueBox.x = player.x;
- dialogueText.x = player.x;
- dialogueBox.y = player.y-50;
- dialogueText.y = player.y-50;
- // Show dialogue box and text
- dialogueBox.visible = true;
- dialogueText.visible = true;
- dialogueText.setText('Thinking...');
- isWaitingResponse = true;
- // Send request to Node backend
- fetch('generatejson', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({ prompt: '你叫糖豆,你喜欢吃大蒜,请十八字以内回答:' + message })
- })
- .then(response => response.json())
- .then(data => {
- console.log(data);
- dialogueText.setText(data.response.replace(/<think>[\s\S]*?<\/think>/g, '').trim());
- isWaitingResponse = false;
- })
- .catch(error => {
- console.error('Error:', error);
- dialogueText.setText('Failed to get response');
- isWaitingResponse = false;
- });
- // Clear input box
- inputBox.value = '';
- }
- function fetchJoke() {
- if (npcIsWaitingResponse) return;
- npcDialogueBox.visible = true;
- npcDialogueText.visible = true;
- npcDialogueText.setText('Thinking...');
- npcIsWaitingResponse = true;
- fetch('generatejson', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({ prompt: '我是糖豆老爸,给我一个俏皮话,十八个字以内' })
- })
- .then(response => response.json())
- .then(data => {
- console.log(data);
- npcDialogueText.setText(data.response.replace(/<think>[\s\S]*?<\/think>/g, '').trim());
- npcIsWaitingResponse = false;
- })
- .catch(error => {
- console.error('Error:', error);
- npcDialogueText.setText('Failed to get response');
- npcIsWaitingResponse = false;
- });
- }
- function changeNPC() {
- const npcSelector = document.getElementById('npc-selector');
- const selectedNPC = npcSelector.value;
- console.log(selectedNPC)
- npcSkin=selectedNPC
- npc.setTexture(selectedNPC);
- npc.setOrigin(0.5);
- npc.setFrame(0);
- }
- </script>
- </body>
- </html>
复制代码
3、素材下载
游戏模版:
图片素材:
https://www.aigei.com/view/72345.html?page=9#resContainer
4、 AI增强
1、chat.deepseek.com
2、https://kimi.moonshot.cn/chat/cujgsroh8njmu15ru2rg
|