Jump to content

[RESOLVIDO] Puzzle - reconhecimento do toque em peças transparentes


Recommended Posts

Posted (edited)

Boas pessoal, estou a desenvolver um jogo em winforms (c#). Trata-se basicamente de um puzzle, com peças que são imagens com transparência.

Pretendo que seja reconhecido o toque sobre qualquer peça, e que a peça selecionada com o "MouseDown" acompanhe o "MouseMove" para se deslocar.

O problema surge quando existe um toque numa das partes transparentes da peça, e quero verificar se existe alguma peça por baixo, de forma a trazer essa para a frente e começar a mover-se.

Já consigo identificar se o toque do rato foi feito na peça ou numa das partes transparentes, no entanto, não estou a conseguir passar o evento do rato corretamente para a peça que se encontra por baixo.

Qual a melhor forma para conseguir o que pretendo? O que estou a fazer de errado?

Deixo aqui algum código para perceberem o que estou a tentar fazer:

FORM:

public partial class Form1 : Form
{
 private List<Peça> peças;
 private Point _Offset = Point.Empty;
 public Form1()
 {
	 InitializeComponent();
	 peças = new List<Peça>();
	 SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
	 criaListaPecas();
	 associaEventosPecas();
 }
 private void associaEventosPecas()
 {
	 foreach (Peça p in peças)
	 {
		 p.MouseMove += Form1_MouseMove;
	 }
 }
 private void criaListaPecas()
 {
	 peças.Clear();
	 foreach (Control p in this.Controls)
	 {
		 if (p.GetType() == typeof(Peça))
			 peças.Add((Peça)p);
	 }
	 Console.WriteLine(peças[0].Name);
	 Console.WriteLine(peças[1].Name);
	 Console.WriteLine(peças[2].Name);
 }
 protected override CreateParams CreateParams
 {
	 get
	 {
		 CreateParams handleParam = base.CreateParams;
		 handleParam.ExStyle |= 0x02000000;
		 return handleParam;
	 }
 }
 private void Form1_MouseMove(object sender, MouseEventArgs e)
 {
	 label1.Text = e.Location.ToString();
	 gereMovimento(e);
 }
 private void gereMovimento(MouseEventArgs e)
 {
	 foreach (Peça p in peças)
	 {
		 if (p.movable)
		 {
			 p.Move(e);
		 }
	 }
 }
}

PEÇA:

class Peça : DrawingArea
{
 private Point _Offset = Point.Empty;
 public Boolean movable = false;
 public Image imagem
 {
	 get;
	 set;
 }
	 protected override void OnDraw()
 {
	 Rectangle location = new Rectangle(0, 0, imagem.Width, imagem.Height);
	 this.graphics.DrawImage(imagem, location);
 }
	 public void Move(MouseEventArgs e)
 {
	 if (_Offset != Point.Empty)
	 {
		 Point newlocation = this.Location;
		 newlocation.X += e.X - _Offset.X;
		 newlocation.Y += e.Y - _Offset.Y;
		 this.Location = newlocation;
	 }
 }
	 protected override void onmouseup(MouseEventArgs e)
 {
	 _Offset = Point.Empty;
	 movable = false;
 }
	 protected override void onmousedown(MouseEventArgs e)
 {
	 Down(e);
 }
	 public Boolean Down(MouseEventArgs e, bool propaga = true)
 {
	 Form parentForm = (this.Parent as Form);
	 Bitmap b = new Bitmap(imagem);
	 Color? color = null;
	 Boolean flag = false;
	 try
	 {
		 color = b.GetPixel(e.X, e.Y);
		 if (color.Value.A != 0 && color != null)
		 {
			 if (e.Button == MouseButtons.Left)
			 {
				 _Offset = new Point(e.X, e.Y);
				 this.BringToFront();
				 flag = true;
				 movable = true;
			 }
		 }
		 else
		 {
			 flag = false;
		 }
		 return flag;
	 }
	 catch
	 {
		 return flag;
	 }
 }
}

DRAWING AREA (PANEL):

abstract public class DrawingArea : Panel
{
 protected Graphics graphics;
 abstract protected void OnDraw();
 protected override CreateParams CreateParams
 {
	 get
	 {
		 CreateParams cp = base.CreateParams;
		 cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
		 return cp;
	 }
 }

 protected override void OnPaint(PaintEventArgs e)
 {

	 this.graphics = e.Graphics;
	 this.graphics.TextRenderingHint =
		 System.Drawing.Text.TextRenderingHint.AntiAlias;
	 this.graphics.InterpolationMode =
		 System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
	 this.graphics.PixelOffsetMode =
		 System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
	 this.graphics.SmoothingMode =
		 System.Drawing.Drawing2D.SmoothingMode.HighQuality;
	 OnDraw();
 }
}

Deixo também uma pequena imagem ilustrativa das peças:

Capture.PNG

Qualquer ajuda é bem-vinda 😉

Obrigado

Edited by morther
Posted

Consegui Resolver o problema agora mesmo, deixo aqui as alterações no código para quem precisar:

(Não liguem à confusão do código, ainda não tive tempo para juntar partes repetidas etc.)

PEÇA:

class Peça : DrawingArea
   {
    private Point _Offset = Point.Empty;
    public Boolean movable = false;
	    public Image imagem
    {
	    get;
	    set;
    }
	    protected override void OnDraw()
    {
	    Rectangle location = new Rectangle(0, 0, imagem.Width, imagem.Height);
	    this.graphics.DrawImage(imagem, location);
    }
	    public Boolean Down(Point e, bool propaga = true)
    {
	    Bitmap b = new Bitmap(imagem);
	    Color? color = null;
	    Boolean flag = false;
	    try
	    {
		    color = b.GetPixel(e.X, e.Y);
		    if (color.Value.A != 0 && color != null)
		    {
			   flag = true;
		    }
		    else
		    {
			    flag = false;
		    }
		    return flag;
	    }
	    catch
	    {
		    return flag;
	    }
    }
   }

FORM:

public partial class Form1 : Form
   {
    private List<Peça> peças;
    private Point _Offset = Point.Empty;
    private Peça peça1, peça2, peça3, peça4;
    private bool canMove;
    private Peça atual;
    private bool other=false;
    public Form1()
    {
	    FormBorderStyle = FormBorderStyle.None;
	    WindowState = FormWindowState.Maximized;
	    InitializeComponent();
	    atual = new Peça();
	    peça1 = new Peça();
	    peça2 = new Peça();
	    peça3 = new Peça();
	    peça4 = new Peça();
	    peça1.imagem = Properties.Resources._4p1_1;
	    peça2.imagem = Properties.Resources._4p1_2;
	    peça3.imagem = Properties.Resources._4p1_3;
	    peça4.imagem = Properties.Resources._4p1_4;
	    peças = new List<Peça>();
	    peça1.Name = "peça1";
	    peça2.Name = "peça2";
	    peça3.Name = "peça3";
	    peça4.Name = "peça4";
	    this.Controls.Add(peça1);
	    this.Controls.Add(peça2);
	    this.Controls.Add(peça3);
	    this.Controls.Add(peça4);
	    criaListaPecas();
	    foreach (Peça p in peças)
	    {
		    p.Size = new Size(p.imagem.Width, p.imagem.Height);
	    }
	    SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);

	    associaEventosPecas();
	    canMove = false;
    }
    private void associaEventosPecas()
    {
	    foreach (Peça p in peças)
	    {
		    p.MouseMove += Form1_MouseMove;
		    p.MouseDown += Form1_MouseDown;
		    p.MouseUp += Form1_MouseUp;
	    }
    }
    private void criaListaPecas()
    {
	    peças.Clear();
	    foreach (Control p in this.Controls)
	    {
		    if (p.GetType() == typeof(Peça))
			    peças.Add((Peça)p);
	    }
	    Console.WriteLine(peças[0].Name);
	    Console.WriteLine(peças[1].Name);
	    Console.WriteLine(peças[2].Name);
	    Console.WriteLine(peças[3].Name);
    }
    protected override CreateParams CreateParams
    {
	    get
	    {
		    CreateParams handleParam = base.CreateParams;
		    handleParam.ExStyle |= 0x02000000;
		    return handleParam;
	    }
    }
    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
	    if (sender.GetType().Equals(typeof(Peça)))
	    {
		    label1.Text = new Point(e.Location.X + (sender as Peça).Location.X, e.Location.Y + (sender as Peça).Location.Y).ToString();
	    }
	    else
	    label1.Text = e.Location.ToString();
	    gereMovimento(sender, e);
    }
    private void gereMovimento(object sender, MouseEventArgs e)
    {
	    if (canMove)
	    {
		    if (other)
		    {
			    Point p = atual.PointToClient(new Point(e.X + (sender as Peça).Location.X, e.Y + (sender as Peça).Location.Y));
			    Point newlocation = atual.Location;
			    newlocation.X += p.X - _Offset.X;
			    newlocation.Y += p.Y - _Offset.Y;
			    atual.Location = newlocation;
		    }
		    else
		    {
			    Point newlocation = atual.Location;
			    newlocation.X += e.X - _Offset.X;
			    newlocation.Y += e.Y - _Offset.Y;
			    atual.Location = newlocation;
		    }
	    }
    }
    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
	    if (sender.GetType().Equals(typeof(Peça)) && e.Button == MouseButtons.Left)
	    {
		    atual = sender as Peça;
		    atual.BringToFront();
		    criaListaPecas();
		    if (atual.Down(e.Location))
		    {
			    _Offset = new Point(e.X, e.Y);
			    canMove = true;
			    other = false;
		    }
		    else
		    {
			    Console.WriteLine(peças[1].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y)));
			    Console.WriteLine(atual.Location);
			    Point p = new Point();
			    if (peças[1].ClientRectangle.Contains(peças[1].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y)))
				    && peças[1].Down(peças[1].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y))))
			    {
				    p = peças[1].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y));
				    atual = peças[1];
				    atual.BringToFront();
				    criaListaPecas();
				    _Offset = p;
				    canMove = true;
				    other = true;
			    }
			    else if (peças[2].ClientRectangle.Contains(peças[2].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y)))
				    && peças[2].Down(peças[2].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y))))
			    {
				    p = peças[2].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y));
				    atual = peças[2];
				    atual.BringToFront();
				    criaListaPecas();
				    _Offset = p;
				    canMove = true;
				    other = true;
			    }
			    else if (peças[3].ClientRectangle.Contains(peças[3].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y)))
				    && peças[3].Down(peças[3].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y))))
			    {
				    p = peças[3].PointToClient(new Point(e.X + atual.Location.X, e.Y + atual.Location.Y));
				    atual = peças[3];
				    atual.BringToFront();
				    criaListaPecas();
				    _Offset = p;
				    canMove = true;
				    other = true;
			    }
		    }
	    }
    }
    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
	    canMove = false;
    }
   }

Alguma questão disponham 😉

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.