最近,我一直致力于一个简单的吃豆人游戏,其中包括两个" Pacmen"随机产卵给他们吃。每当Pacman靠近石头时,我真的想尝试让石头离开它们,但我不确定这是怎么做的。有人可能会看看我的代码并给我一些建议吗?谢谢,我真的很感激!
Form1代码文件:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;
using System.Media;
namespace EaterGame1
{
public partial class Form1 : Form
{
[DllImport("winmm.dll")]
public static extern long PlaySound(String lpszName, long hModule, long dwFlags);
private ArrayList Stones = new ArrayList(30);
private Eater TheEater = new Eater(100, 100);
private Eater TheOtherEater = new Eater(100, 50);
private Random RandomGen = new Random();
private const int NumberOfStones = 100;
private Score TheScore = new Score(640, 350);
private Score TheOtherScore = new Score(640, 330);
private int TheSeconds = 0;
private TimerDisplay TheTime = new TimerDisplay(7, 350);
//private System.Windows.Forms.Timer timer1;
//private System.ComponentModel.IContainer components;
private Thread oThread = null;
public Form1()
{
InitializeComponent();
InitializeStones();
InitializeTimer();
// reduce flicker
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
}
private string m_strCurrentSoundFile = "miss.wav";
public void PlayASound()
{
if (m_strCurrentSoundFile.Length > 0)
{
//PlaySound(Application.StartupPath + "\\" + m_strCurrentSoundFile, 0, 0);
SoundPlayer simpleSound = new SoundPlayer(Application.StartupPath + "\\" + m_strCurrentSoundFile);
simpleSound.Play();
}
m_strCurrentSoundFile = "";
oThread.Abort();
}
public void PlaySoundInThread(string wavefile)
{
m_strCurrentSoundFile = wavefile;
oThread = new Thread(new ThreadStart(PlayASound));
oThread.Start();
}
public void InitializeTimer()
{
timer1.Start();
}
public void InitializeStones()
{
for (int i = 0; i < NumberOfStones; i++)
{
Stones.Add(new Stone(RandomGen.Next(
10, ClientRectangle.Right - 10),
RandomGen.Next(10, ClientRectangle.Bottom - 30)));
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
string result = e.KeyData.ToString();
Invalidate(TheEater.GetFrame());
Invalidate(TheOtherEater.GetFrame());
switch (result)
{
case "Left":
TheEater.MoveLeft(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
case "Right":
TheEater.MoveRight(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
case "Up":
TheEater.MoveUp(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
case "Down":
TheEater.MoveDown(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
case "E":
TheOtherEater.MoveNorthWest(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
case "Q":
TheOtherEater.MoveNorthEast(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
case "C":
TheOtherEater.MoveSouthWest(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
case "Z":
TheOtherEater.MoveSouthEast(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
case "W":
TheOtherEater.MoveUp(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
case "A":
TheOtherEater.MoveLeft(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
case "D":
TheOtherEater.MoveRight(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
case "X":
TheOtherEater.MoveDown(ClientRectangle);
Invalidate(TheOtherEater.GetFrame());
break;
default:
break;
}
int hit = CheckIntersection();
if (hit != -1)
{
TheScore.Increment();
PlaySoundInThread("hit.wav");
Invalidate(TheScore.GetFrame());
Invalidate(((Stone)Stones[hit]).GetFrame());
Stones.RemoveAt(hit);
if (Stones.Count == 0)
{
MessageBox.Show("You Win!\nYour time is " + TheTime.TheString + " seconds.\nThe first eater ate " + TheScore + " stones!\nThe second eater ate " + TheOtherScore + " stones!");
Application.Exit();
}
}
int hit2 = CheckIntersection2();
if(hit2 != -1)
{
TheOtherScore.Increment();
PlaySoundInThread("hit.wav");
Invalidate(TheOtherScore.GetFrame());
Invalidate(((Stone)Stones[hit2]).GetFrame());
Stones.RemoveAt(hit2);
if (Stones.Count == 0)
{
MessageBox.Show("You Win!\nYour time is " + TheTime.TheString + " seconds.\nThe first eater ate " + TheScore + " stones!\nThe second eater ate " + TheOtherScore + " stones!");
Application.Exit();
}
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, 0, 0, this.ClientRectangle.Width, ClientRectangle.Height);
// draw the score
TheScore.Draw(g);
TheOtherScore.Draw(g);
// draw the time
TheTime.Draw(g, TheSeconds);
// draw the stones
for (int i = 0; i < Stones.Count; i++)
{
((Stone)Stones[i]).Draw(g);
}
// also draw the eater
TheEater.Draw(g);
TheOtherEater.Draw(g);
}
private int CheckIntersection()
{
for (int i = 0; i < Stones.Count; i++)
{
Rectangle stoneRect = ((Stone)Stones[i]).GetFrame();
if (TheEater.GetFrame().IntersectsWith(stoneRect))
{
return i;
}
}
return -1;
}
private int CheckIntersection2()
{
for (int i = 0; i < Stones.Count; i++)
{
Rectangle stoneRect = ((Stone)Stones[i]).GetFrame();
if (TheOtherEater.GetFrame().IntersectsWith(stoneRect))
{
return i;
}
}
return -1;
}
private void timer1_Tick(object sender, EventArgs e)
{
TheSeconds++;
Invalidate(TheTime.GetFrame());
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
食者代码文件:
using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace EaterGame1
{
/// <summary>
/// Eats all the dots
/// </summary>
public class Eater
{
public Point Position;
static Bitmap EaterImage = null;
static Bitmap EaterImage2 = null;
static Bitmap EaterImage3 = null;
static Bitmap EaterImage4 = null;
int inc = 3;
int LastPositionX = 0;
int LastPositionY = 0;
public Eater()
{
//
// TODO: Add constructor logic here
//
Position.X = 30;
Position.Y = 35;
if (EaterImage == null)
{
EaterImage = new Bitmap("eater.gif");
}
if (EaterImage2 == null)
{
EaterImage2 = new Bitmap("eater2.gif");
}
if(EaterImage3 == null)
{
EaterImage3 = new Bitmap("eater3.gif");
}
if (EaterImage4 == null)
{
EaterImage4 = new Bitmap("eater4.gif");
}
}
public Eater(int x, int y)
{
//
// TODO: Add constructor logic here
//
Position.X = x;
Position.Y = y;
if (EaterImage == null)
{
EaterImage = new Bitmap("eater.gif");
}
if (EaterImage2 == null)
{
EaterImage2 = new Bitmap("eater2.gif");
}
if (EaterImage3 == null)
{
EaterImage3 = new Bitmap("eater3.gif");
}
if (EaterImage4 == null)
{
EaterImage4 = new Bitmap("eater4.gif");
}
}
public Rectangle GetFrame()
{
Rectangle myRect = new Rectangle(Position.X, Position.Y, EaterImage.Width, EaterImage.Height);
return myRect;
}
public void Draw(Graphics g)
{
Rectangle destR = new Rectangle(Position.X, Position.Y, EaterImage.Width, EaterImage.Height);
Rectangle srcR = new Rectangle(0, 0, EaterImage.Width, EaterImage.Height);
// make it look like the mouth is moving
if (((Position.X % 2 == 1) && ((Position.X - LastPositionX) != 0)) ||
((Position.Y % 2 == 1) && ((Position.Y - LastPositionY) != 0))
)
g.DrawImage(EaterImage, destR, srcR, GraphicsUnit.Pixel);
else
g.DrawImage(EaterImage2, destR, srcR, GraphicsUnit.Pixel);
if (((Position.X % 2 == 1) && ((Position.X - LastPositionX) != 0)) ||
((Position.Y % 2 == 1) && ((Position.Y - LastPositionY) != 0))
)
g.DrawImage(EaterImage3, destR, srcR, GraphicsUnit.Pixel);
else
g.DrawImage(EaterImage4, destR, srcR, GraphicsUnit.Pixel);
LastPositionX = Position.X;
LastPositionY = Position.Y;
}
public void MoveLeft(Rectangle r)
{
if (Position.X <= 0)
return; // precondition
Position.X -= inc;
}
public void MoveRight(Rectangle r)
{
if (Position.X >= r.Width - EaterImage.Width)
return; // precondition
Position.X += inc;
}
public void MoveUp(Rectangle r)
{
if (Position.Y <= 0)
return; // precondition
Position.Y -= inc;
}
public void MoveDown(Rectangle r)
{
if (Position.Y >= r.Height - EaterImage.Height)
return; // precondition
Position.Y += inc;
}
public void MoveNorthWest(Rectangle r)
{
MoveUp(r);
MoveRight(r);
}
public void MoveNorthEast(Rectangle r)
{
MoveUp(r);
MoveLeft(r);
}
public void MoveSouthWest(Rectangle r)
{
MoveDown(r);
MoveRight(r);
}
public void MoveSouthEast(Rectangle r)
{
MoveDown(r);
MoveLeft(r);
}
}
}
石头代码文件:
using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace EaterGame1
{
/// <summary>
/// Summary description for Stone.
/// </summary>
public class Stone
{
public Point Position;
static Bitmap StoneImage = null;
public Stone()
{
//
// TODO: Add constructor logic here
//
Position.X = 0;
Position.Y = 0;
if (StoneImage == null)
{
StoneImage = new Bitmap("stone.gif");
}
}
public Stone(int x, int y)
{
//
// TODO: Add constructor logic here
//
Position.X = x;
Position.Y = y;
if (StoneImage == null)
{
StoneImage = new Bitmap("stone.gif");
}
}
public Rectangle GetFrame()
{
Rectangle myRect = new Rectangle(Position.X, Position.Y, StoneImage.Width, StoneImage.Height);
return myRect;
}
public void Draw(Graphics g)
{
Rectangle destR = new Rectangle(Position.X, Position.Y, StoneImage.Width, StoneImage.Height);
Rectangle srcR = new Rectangle(0, 0, StoneImage.Width, StoneImage.Height);
g.DrawImage(StoneImage, destR, srcR, GraphicsUnit.Pixel);
}
}
}
答案 0 :(得分:0)
我会给石头一个方法(一帧一次调用)到效果:
public void Move(Point eater){
xDif = Position.x - eater.x;
if(xDif != 0) Position.x += inc*(xDif)/abs(xDif);
//you will need similar code to address the y
}
其中inc是你希望石头移动的速度。该算法适用于移动开放空间和封闭空间。您仍然需要使用代码来防止石头进入墙壁,但感觉我没有看到您用于墙壁的任何代码,我无法帮助您。
答案 1 :(得分:0)
我会创建一个新方法并将其放在program.cs中的switch语句中。
我的代码并不完美,但我希望这可以解决这个问题。
switch (result)
{
case "Left":
TheEater.MoveLeft(ClientRectangle);
Invalidate(TheEater.GetFrame());
CheckIfEaterIsCloseToMe(); // new method
break;
case "Right":
TheEater.MoveRight(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
...
private void CheckIfEaterIsCloseToMe()
{
for (int i = 0; i < Stones.Count; i++)
{
Rectangle stoneRect = ((Stone)Stones[i]).GetFrame();
if (TheOtherEater.GetFrame().IsClose(stoneRect, TheOtherEater.GetFrame()))
{
// call move method maybe - or just move
}
}
}
private bool IsClose(Rectange r1, Rectangle r2)
{
// check if the r1 is close to r2 -- get the left - right - top - bottom of each rectangle
// first you need to determine if the other rectangle is on the left or right or top or bottom of this rectangle
if( ( (r1.X + r1.Width) - r2.X) <= 20 ) // 20 is threshold -- if on the right -- take the right side minus left side
{
// move stone how you want -> maybe to the right more
return true;
}
return false;
}