想要放10顆球在裡面一起跑(不考慮碰球跟球之間的碰撞)
也就是picturebox4~12都要寫一樣的東西
試問這樣的迴圈寫法要如何著手?謝謝大家
目前寫了兩顆球用這種方式:
還有很多顆要重複寫一樣的東西,求大師指點要如何使用迴圈
盡量不要用可視元件(Control)當做動畫元素,因為系統繪製Control的過程需要大量處理器及時間
以下是我草草寫的程式,沒用到DirectX/OpenGL
VS2019 + C# + .NetCore 3.1 + WinForm(你也可以一字不漏的抄也能在其他.net framework版本上跑,沒有系統依賴)
主程式只用到填滿Form的panel和timer,未用到其他元件或程式庫,程式下方的ball是一個自定class
(放在公司的雲端共享空間,請自行下載)
http://mail.jho.com.tw/owncloud/index.php/s/BwG5aTK8jN8Ej8L
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace pinBall
{
public partial class Form1 : Form
{
List<ball> balls = new List<ball>();
public Form1()
{
InitializeComponent();
}
private void drawballs(Graphics g)
{
foreach (var b in balls)
{
using (Brush sb = new SolidBrush(b.color))
{
g.FillEllipse(sb, b.pos.X-b.r, b.pos.Y-b.r, b.R, b.R);
}
b.move(); // 把球球的下一步都算好
}
}
private void Form1_Load(object sender, EventArgs e)
{
// 產生10個球並存入 List of ball裡
for (int b = 1; b <= 10; b++)
{
//依Form畫面尺寸準備10個小球
balls.Add(new ball(Width, Height, 50));
}
timer1.Interval = 100; // 每秒10 FPS
timer1.Enabled = true; // 打開畫球的Timer
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
drawballs(e.Graphics); // 畫球
}
private void timer1_Tick(object sender, EventArgs e)
{
panel1.Invalidate(); // 重新繪製畫面(會引發panel1_Paint事件)
}
}
// 主程式結束
// 以下是球球所需要的class , 讓每個球都有自己的屬性及運算軌跡方式
class ball
{
public Color color { get; set; }
public PointF pos { get; set; }
public int directionX { get; set; }
public int directionY { get; set; }
public int R { get; set; }
public float r { get; set; } //半徑
private int pWidth { get; set; }
private int pHeight { get; set; }
public ball(int width, int height, int ballR)
{
Random rnd = new Random(Guid.NewGuid().GetHashCode());
pos = new PointF(rnd.Next(ballR, width - ballR), rnd.Next(ballR, height - ballR));
directionX = 5 - rnd.Next(10);
directionY = 5 - rnd.Next(10);
R = ballR; // 直徑
r = R / 2;
pWidth = width;
pHeight = height;
color = Color.FromArgb(255, rnd.Next(255), rnd.Next(255), rnd.Next(255));
}
public void move()
{
// 如果下一步超過畫面 ... 大於寬高或小於0的話,則折返,方法就是直接把X跟Y移動值正負顛倒就對了!
if (pos.X + directionX + R >= pWidth)
{
directionX *= -1;
}
if ((pos.X + directionX) - R <= 0)
{
directionX = Math.Abs(directionX);
}
if (pos.Y + directionY + R >= pHeight)
{
directionY *= -1;
}
if ((pos.Y + directionY) - R <= 0)
{
directionY = Math.Abs(directionY);
}
pos = new PointF(pos.X+ directionX,pos.Y + directionY);
}
}
}
沒打開doublebuffer,所以會有些閃爍的,請見諒
真要動畫跑的順,不閃爍的話,你還非得要用到Unity(或全手工跑OpenGL/DirectX)來做不可哩,不過那對新手而言實在是有點高牆,連我自己都學藝不精,所以不敢現醜啦
您好,現在已將這四個picturebox寫入陣列裡,但是活動範圍變得很奇怪,每顆球幾乎都各自在紅色框框的範圍內撞
for(int Ball=0; Ball < 4; Ball++)
{
switch (i % 2)
{
case 0:
if (pictureBoxArray[Ball].Left < panel1.Width - pictureBoxArray[Ball].Width)
{
pictureBoxArray[Ball].Left = pictureBoxArray[Ball].Left + 10;
}
else
{
i = i + 1;
}
break;
case 1:
if (pictureBoxArray[Ball].Left > 0)
{
pictureBoxArray[Ball].Left = pictureBoxArray[Ball].Left - 10;
}
else
{
i = i - 1;
}
break;
}
switch (j % 2)
{
case 0:
if (pictureBoxArray[Ball].Top < panel1.Height - pictureBoxArray[Ball].Height)
{
pictureBoxArray[Ball].Top = pictureBoxArray[Ball].Top + 10;
}
else
{
j = j + 1;
}
break;
case 1:
if (pictureBoxArray[Ball].Top > 0)
{
pictureBoxArray[Ball].Top = pictureBoxArray[Ball].Top - 10;
}
else
{
j = j - 1;
}
break;
}
}
也想請問
pictureBoxArray[0] = pictureBox1;
pictureBoxArray[1] = pictureBox2;
pictureBoxArray[2] = pictureBox3;
pictureBoxArray[3] = pictureBox4;
因為我有49張圖,想問這種還有別種寫法嗎(迴圈)?
不要用pictureBox這類"Control可視元件",你只要畫面上有十個可視元件,卡頓會讓你叫不敢
如果真的非這樣做不可,那就
List<PictureBox> pictures = new List<PictureBox>();
for(int x = 1 ; x<=49;x ++){
PictureBox pb = new PictureBox();
pb.Left = 10;
pb.Top = 20;
pb.Parent = Form1;
pictures.Add(pb);
}
想請問.parent是指甚麼?
親代窗口,放這個picturebox的Control,通常為form或panel
不過我程式寫錯了,你改一下
pb.Parent = this ;
或
this.Controls.Add(pb);
我最開頭的程式修改一下,不用放panel,把form的屬性doublebuffer 設成enable
程式改成以下,Timer.interval 改成 30 (33 FPS)都不會閃爍了!
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace pinBall
{
public partial class Form1 : Form
{
List<ball> balls = new List<ball>();
public Form1()
{
InitializeComponent();
}
private void drawballs(Graphics g)
{
foreach (var b in balls)
{
using (Brush sb = new SolidBrush(b.color))
{
g.FillEllipse(sb, b.pos.X - b.r, b.pos.Y - b.r, b.R, b.R);
}
b.move(); // 下一步
}
}
private void Form1_Load(object sender, EventArgs e)
{
for (int b = 1; b <= 10; b++) // 產生10個球並存入 List of ball裡
{
balls.Add(new ball(Width, Height, 50));
}
timer1.Interval = 30;
timer1.Enabled = true;
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
drawballs(e.Graphics);
}
}
class ball
{
public Color color { get; set; }
public PointF pos { get; set; }
public int directionX { get; set; }
public int directionY { get; set; }
public int R { get; set; }
public float r { get; set; } //半徑
private int pWidth { get; set; }
private int pHeight { get; set; }
public ball(int width, int height, int ballR)
{
Random rnd = new Random(Guid.NewGuid().GetHashCode());
pos = new PointF(rnd.Next(ballR, width - ballR), rnd.Next(ballR, height - ballR));
directionX = 5 - rnd.Next(10);
directionY = 5 - rnd.Next(10);
R = ballR; // 直徑
r = R / 2;
pWidth = width;
pHeight = height;
color = Color.FromArgb(255, rnd.Next(255), rnd.Next(255), rnd.Next(255));
}
public void move()
{
if (pos.X + directionX + R >= pWidth)
{
directionX *= -1;
}
if ((pos.X + directionX) - R <= 0)
{
directionX = Math.Abs(directionX);
}
if (pos.Y + directionY + R >= pHeight)
{
directionY *= -1;
}
if ((pos.Y + directionY) - R <= 0)
{
directionY = Math.Abs(directionY);
}
pos = new PointF(pos.X + directionX, pos.Y + directionY);
}
}
}
謝謝您~
picturebox可以在後端產生,
其實你寫在WinForm也是會有一些後端的程式碼,
可以到另外一個檔案(通常是desinger.cs)去看picturebox的宣告.
用一個PictureBox的陣列放這些picturebox,
就可以用迴圈來產生跟運動了.
迴圈的部分我不是很清楚本人沒碰過幾次..可以加以解說指點嗎謝謝不好意思
類似這樣吧...
List<PictureBox> pictureList;
function 建構式()
{
pictureList = new List<PictureBox>();
}
function xxx()
{
for(int i=0;i<?;i++)
{
PictureBox picture = new PictureBox();
picture.Left = xxx;
picture.Top = xxx;
...
...
plctureList.add(picture);
}
}
之類的,
不過要把picturebox加到control中.