[c#] obsluga dwoch klawiszy naraz..?

0

witam,

w jaki sposób dowiedzieć się że zostały naciśnięte dwa klawisze?
przykładowo jest taka sytuacja że gracz naciska strzałke do góry i obiekt sie porusza, i trzymając strzałke do góry wciśniętą naciska dodatkowo strzałke w lewo - co odpowiada poruszaniu sie obiektu w lewo
jak ten problem rozwiazac?

0

no ok, dzieki,

ale cos mi nie dziala, mam taki kod:

private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
                if (e.KeyCode == Keys.Up) isDownUp = true;
                 
                if (e.KeyCode == Keys.Left) isDownLeft = true;
                   
                if (e.KeyCode == Keys.Right) isDownRight = true;


                if (isDownUp) MessageBox.Show("UP");
                if (isDownLeft) MessageBox.Show("LEFT");
                if (isDownRight) MessageBox.Show("RIGHT");

                
                /*if (isDownUp) pow.movePlane();
                if (isDownLeft) pow.obr(-15.0);
                if (isDownRight) pow.obr(15.0);*/
            
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up)    isDownUp = false;
            else
            if (e.KeyCode == Keys.Left)  isDownLeft = false;
            else
            if (e.KeyCode == Keys.Right) isDownRight = false;
        }

problem polega na tym, że po tym jak klikne "UP" i potem np klikne dowolny klawisz to zawsze wyskakuje okienko ze kliknalem "UP"
przykladowo: uruchamiam program, klikam dowolny klawisz (za wyjatkiem :UP, LEFT, RIGHT) ,jest ok, czyli nic sie nie robi, a jak klikne np UP, to potem jak klikne dowolny to tez UP wyskakuje...

dzieki z gory za pomoc
pozdrawiam

0

Ale czy dokładnie tak zrobiłeś jak w tamtym poście ? Nie wydaje mi się. Zrób krok po kroku jak jest tam opisane, a na pewno Ci zadziała. Zadeklaruj klasę, nadpisz odpowiednią metodą. KeyUp i KeyDown nie pomogą Ci ;)

0

spoko, dziala tak samo, mozesz zerknac na efekt :
<url>
http://www.speedyshare.com/872730882.html
</url>
chcialbym zlikwidowac dwa nieporzadane efekty:

  1. Jesli mam wcisniety UP i nie puszczajac go wcisne np LEFT i potem puszcze LEFT (non stop trzymajac UP), to obiekt sie mimo wszystko zatrzymuje, a chcialbym aby lecial prosto.

  2. Kolejny problem to to że jak trzymajac UP naciskam dowolny klawisz (LEFT, badz RIGHT) to obiekt zanim zacznie sie obraca w odpowiednia strone chwile czeka....

Jesli jest mozliwosc wyslalbym kod na priv,
jutro bede, to pogadamy

pozdrawiam i dzieki za zainteresowanie

0

oczywiscie na formularzu powienienes ustawic flage KeyPreview na true:
this.KeyPreview = true;

odpal sobie spy++ (narzedzie w kazdym visual studio, ale chyba nie w expressach) i zobacz jakie leca komunikaty, u mnie wyglada to tak:
trzymam przycisk1
WM_KEYDOWN przycisk1...
nie puszczajac przycisk1 wciskam przycisk2
WM_KEYDOWN przycisk2...
puszczam przycisk2 (majac nadal wcisniety przycisk1)
WM_KEYUP przycisk2
i teraz nic, kolejne komunikaty nie leca o tym ze przycisk1 jest dalej wcisniety

moze faktycznie uzycie mechanizmow z DirectX bedzie pomocne

0

to ja quote ;-)
ok, zamieszczam kod, bo pewnie coś w kodzie skaszaniłem,
mam 3 pliki:

  • "biblioteka graficzna" - nie mojego autorstwa
  • klasa statku
  • glowny plik

a więc biblioteka najpierw: rawBitmap.cs:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;


namespace bibliotekaGFX
{
    public class rawBitmap
    {
        public Bitmap bitmap;
        public IntPtr bitmapDataPtr;
        
        public int width = 0;       //wymiar w pixelach
        public int height = 0;      //wymiar w pixelach

        public int scanLineByteWidth = 0;    // wielkość w bajtach pojedynczej linii;

        public rawBitmap(int _width, int _height)
        {
            width   = _width;
            height  = _height;

            scanLineByteWidth = 2048 * 4;  //zatem jedna linia może przechowywać maksymalnie 2048 punktów
                                           //zastanów się jak takie uproszczenie wpływa na szybkość.

            bitmapDataPtr = Marshal.AllocHGlobal(scanLineByteWidth * height);

            bitmap = new Bitmap(width, height, scanLineByteWidth, System.Drawing.Imaging.PixelFormat.Format32bppRgb, bitmapDataPtr);            
        }

        public void setPixelAsRGB(int x, int y, byte rR, byte rG, byte rB)
        {
            if (x < 0 || x > width- 1 ) return;
            if (y < 0 || y > height - 1) return;

            Marshal.WriteInt32(bitmapDataPtr, (y<<13) + (x<<2), (rR<<16)+ (rG<<8) + rB);
        }

        public void clear()
        {
            int ofs = 0;
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width * 4; i += 4)
                {
                    Marshal.WriteInt32(bitmapDataPtr, ofs + i, 0);
                }
                ofs += scanLineByteWidth;
            }
        }

        public void freeMemory()
        {
            Marshal.FreeHGlobal(bitmapDataPtr);
        }

        public void drawLine(int aX, int aY, int bX, int bY,byte rR, byte rG, byte rB)
        {
            double dlugosc = Math.Sqrt((bX - aX) * (bX - aX) + (bY - aY) * (bY - aY));
            if (dlugosc == 0) dlugosc = 1;
            double deltaT = 1.0 / dlugosc;
            
            double Vx = bX-aX;
            double Vy = bY-aY;

            double T = 0;

            while (T <= 1)
            {
                double pX = (double)aX + Vx * T;
                double pY = (double)aY + Vy * T;
                T += deltaT;
                setPixelAsRGB((int)pX, (int)pY, rR, rG, rB);
            }

        }
    }
}

teraz klasa statku ship.cs:

using System;
using System.Collections.Generic;
using System.Text;
using bibliotekaGFX;

namespace Plane
{
    class ship
    {
        //ekran virtualny
        rawBitmap space;

        //ekran rzeczywisty
        System.Windows.Forms.PictureBox surface;

        //szerokosc i wysokosc ekranu virtualnego - rzeczywistego
        int width;
        int height;

        //wspolrzedne statku, i vektor przesuniecia
        int[,] wsp = new int[4, 2];
        int[] vekt = new int[2];


        public ship(int x, int y, int szerokosc, int wysokosc, System.Windows.Forms.PictureBox pic)
        {
            width = szerokosc;
            height = wysokosc;
            surface = pic;

            //wypelnienie wspolrzednych
            wsp[0, 0] = x;
            wsp[0, 1] = y;

            wsp[1, 0] = wsp[0, 0] - 10;
            wsp[1, 1] = wsp[0, 1] - 10;

            wsp[2, 0] = wsp[0, 0];
            wsp[2, 1] = wsp[0, 1] + 10;

            wsp[3, 0] = wsp[0, 0] + 10;
            wsp[3, 1] = wsp[0, 1] - 10;

            //wektor przesuniecia
            vekt[0] = 0;
            vekt[1] = 0;

            space = new rawBitmap(this.width, this.height);
            surface.Image = space.bitmap;
            draw();
        }

        private void draw()
        {
            space.clear();
            space.drawLine(wsp[0, 0], wsp[0, 1], wsp[1, 0], wsp[1, 1], 255, 255, 255); // linia 0-1
            space.drawLine(wsp[1, 0], wsp[1, 1], wsp[2, 0], wsp[2, 1], 255, 255, 255); // linia 1-2
            space.drawLine(wsp[2, 0], wsp[2, 1], wsp[3, 0], wsp[3, 1], 255, 255, 255); // linia 2-3
            space.drawLine(wsp[3, 0], wsp[3, 1], wsp[0, 0], wsp[0, 1], 255, 255, 255); // linia 3-0
            surface.Refresh();
        }

        public void rotate(double val)
        {
            double a = Math.PI * val / 180.0;
            double sinx = Math.Sin(a);
            double cosx = Math.Cos(a);

            for (int i = 1; i < 4; i++)
            {
                int xx = Convert.ToInt32(wsp[0, 0] + (wsp[i, 0] - wsp[0, 0]) * cosx - (wsp[i, 1] - wsp[0, 1]) * sinx);
                int yy = Convert.ToInt32(wsp[0, 1] + (wsp[i, 1] - wsp[0, 1]) * cosx + (wsp[i, 0] - wsp[0, 0]) * sinx);

                wsp[i, 0] = xx;
                wsp[i, 1] = yy;
            }

            draw();
        }

        public void move()
        {
            vekt[0] = wsp[2, 0] - wsp[0, 0];
            vekt[1] = wsp[2, 1] - wsp[0, 1];

            for (int i = 0; i < 4; i++)
            {
                wsp[i, 0] += vekt[0];
                wsp[i, 1] += vekt[1];
            }

            draw();
        }
    }
}

i plik glowny formy: Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace Plane
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll")]
        static extern short GetKeyState(int nVirtKey);
        private int WM_KEYDOWN = 0x100;

        ship statek;

        public Form1()
        {
            InitializeComponent();
            statek = new ship(100, 200, sur.Width, sur.Height, sur);
            this.KeyPreview = true;
        }


        protected override bool ProcessKeyMessage(ref Message m)
        {
            if (m.Msg.Equals(WM_KEYDOWN))
            {
                if ((GetKeyState(VirtualKeys.VK_UP) & 0x80) == 0x80)
                {
                    statek.move();
                }
                if ((GetKeyState(VirtualKeys.VK_LEFT) & 0x80) == 0x80)
                {
                    statek.rotate(-15);
                }
                if ((GetKeyState(VirtualKeys.VK_RIGHT) & 0x80) == 0x80)
                {
                    statek.rotate(15);
                }
            }
            return base.ProcessKeyMessage(ref m);
        }
    }


    public static class VirtualKeys
    {
        public const int VK_UP =    0x26;
        public const int VK_DOWN =  0x28;
        public const int VK_RIGHT = 0x27;
        public const int VK_LEFT =  0x25;
    }
}

proszę o jakieś uwagi, głównie niegatywne, o stylu pisanie, etc
a ja biore się za directX
pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1