Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.
Nástěnka
❗22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
❗04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
❗23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.
Nejste přihlášen(a). Přihlásit
Ahoj; zdravím Tě tu,
Mám napsané ovládání pomocí události KeyDown();. Problém je ten, že to sežere pouze 4 základní směry (nahoru, dolu, doleva a doprava). Chtěl bych program upravit tím, že bych objekt ovládal do více směrů. Vím, že se to bude dělat pomocí Math.sin a Math.cos. Bohužel ale nemám žádnou myšlenku, jak to naprogramovat. Je tu plno dobrých programátorů a matematiků, tak budu rád, když mi s tím píchneš. Jedná se tedy o implementaci v jazyce C#; díky.
Offline

Ahoj, můžeš to prosím formulovat nějak jinak, přesněji, není mi vůbec jasné, co vlastně potřebuješ :-) (uveď nejlépe konkrétní příklad)
Offline
Ano, popíšu (doufám) srozumitelněji. Dejme tomu, že mám grafický objekt, který ovládám pomocí události keyDown();. Tento objekt ovládám šipkami na klávesnici. To znamená, že (teď) mám udělanou implementaci pro čtyři základní směry (nahoru, dolů, doleva a doprava). Program bych chtěl vylepšit o to, aby se objekt uměl pohybovat do vše směrů (all directions). Takže pokud budu mačkat šipkou doprava, objekt se bude jakoby "nakláněl" na tu pravotočivou část. K tomuto se zajisté využivají funkce jako Math.sin a Math.cos. Doufám, že už je vše více srozumitelnější.
Offline

↑ RePRO:
Aha, už asi chápu. Takže když budu mačkat doleva/doprava, objekt se nebude hýbat, bude se pouze otáčet kolem vlastní osy. Teprve při nahoru/dolu půjde buď ve směru kam je natočený nebo bude couvat v opačném směru. Ty to chceš mít tak, že se objekt bude při stisknuté klávese pohybovat/natáčet konstantní rychlostí. To je tedy to, co chceš vědět jak naprogramovat nebo je to jinak?
Offline
↑ BrozekP: Ano, přesně tak, jak píšeš.
Offline

Tak např. udělej proměnnou alfa, která bude znamenat natočení objektu - úhel v radiánech měřený od "nahoru" ve smyslu hodinových ručiček. Předpokládám, že máš uloženou pozici objektu, dejme tomu, že to budou dvě proměnné poloha.x a poloha.y Pokud se pak má objekt posunout kousek dopředu, stačí provést
poloha.x += K*Math.sin(alfa);
poloha.y += K*Math.cos(alfa);
K si nějak zvol sám, to má význam délky posunutí. Při posunutí dozadu to budeš odečítat. Pro natočení ve směru hodinových ručiček pak bude
alfa += UHEL;
proti směru
alfa -= UHEL;
Zase si UHEL zvol libovolně, má význam o kolik se objekt otočí při provedení příkazu.
EDIT: pokud bys chtěl otáčení/posunování dělat plynule, tak pak asi jedině opakovaně provádět tyto příkazy s malým K a UHEL. To ale nevím, jak v C# udělat.
Offline

struct Poloha
{
public float x, y;
}
class Objekt
{
float alfa;
Poloha poloha;
public void Jdi(float krok)
{
poloha.x += krok*Math.sin(alfa);
poloha.y += krok*Math.cos(alfa);
}
public void OtocSe(float uhel)
{
alfa += uhel;
}
// ...
}A pak můžeš někde v událostech KeyDown spustit nějaký Timer, při KeyUp ho vypnout. Interval Timeru nastavíš na nějakou malou hodnotu a při každé události Tick pak zavoláš jednu z funkcí objektu (podle toho, jaká klávesa je stisknutá, to si třeba někam uložíš).
public int klavesa;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
klavesa = e.KeyValue;
timer1.enabled = true;
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
timer1.enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
switch (klavesa)
{
Keys.down :
objekt.Jdi(0.001); // Půjde dopředu
break;
Keys.up :
objekt.Jdi(-0.001); // Půjde dozadu
break;
Keys.right :
objekt.OtocSe(0.001); // Otočí se doprava
break;
Keys.left :
objekt.OtocSe(-0.001); // Otočí se doleva
break;
}
}To, že si objekt musíš nejdřív vytvořit atd. psát nebudu.
Nejspíš to bude chtít ještě doladit, netestoval jsem to. Taky je pravděpodobné, že bude nějaké lepší řešení, budu rád, pokud ho někdo jiný napíše, sám se teď učím programovat v C#, tak se rád něco přiučím.
Offline
↑ BrozekP: Tvůj nápad se mi moc líbí! Dodělám to své, a hodím Ti sem celej zdroják. Já dělám se C# asi 2 roky. Je to hodně pěknej jazyk.
Offline

Nerozumím. Ten objekt, který chceš, aby se pohyboval, musí mít přeci nějakou polohu, tak jak jinak bys ji chtěl ukládat než jako reálná čísla?
Offline
↑ BrozekP: No, ale pokud to bude vše INT, tak to to nebude házet do toho úhlu, ne?
Offline

↑ RePRO:
A jak by ses chtěl ve čtvercové síti (to by odpovídalo integerům) pohybovat pod určitým úhlem? Když začnu v bodě (0,0) a udělám krok délky 1 v severovýchodním směru, tak v kterém bodě mřížky skončím?
Offline
↑ BrozekP: No jo, ale který objekt přebírá float x a float y jako souřadnice? Žádný.
Offline
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Snake
{
public partial class Form1 : Form
{
List <Food> seznamJidla = new List<Food>();
List<Form1> seznamBodu = new List<Form1>();
Graphics g;
Random nahodneJidlo;
string direction;
int prictiBod = 0;
float alfa;
int x;
int y;
public Form1()
{
InitializeComponent();
g = CreateGraphics();
nahodneJidlo = new Random();
}
private void Form1_Load(object sender, EventArgs e)
{
Timer timer = new Timer();
timer.Start();
timer.Interval = 5;
timer.Tick += new EventHandler(timer_Tick);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left: direction = "left"; break;
case Keys.Right: direction = "right"; break;
case Keys.Down: direction = "down"; break;
case Keys.Up: direction = "up"; break;
}
}
void timer_Tick(object sender, EventArgs e)
{
switch (direction)
{
case "left": otocSe(-0.001f); break;
case "right": otocSe(0.001f); break;
case "down": jdi(0.001f); break;
case "up": jdi(-0.001f); break;
}
label1.Text = x.ToString();
label4.Text = y.ToString();
kresliHada();
}
public void kresliHada()
{
Rectangle re = new Rectangle(x, y, 8, 8);
g.FillRectangle(Brushes.BlueViolet, re);
}
public void vygenerujJidlo()
{
seznamJidla.Add(new Food(nahodneJidlo.Next(0,ClientRectangle.Width),nahodneJidlo.Next(0, ClientRectangle.Height)));
foreach(Food f in seznamJidla)
{
g.DrawRectangle(new Pen(Color.Green), x, y, 200, 200);
label7.Text = f.Xova.ToString();
label8.Text = f.Yova.ToString();
}
}
public void naraziNaJidlo()
{
foreach (Food f2 in seznamJidla)
{
if ((f2.Xova == x) && (f2.Yova == y))
{
prictiBod++;
vygenerujJidlo();
}
}
}
public void jdi(float krok)
{
x += (int)(krok * Math.Sin(alfa));
y += (int)(krok * Math.Cos(alfa));
}
public void otocSe(float uhel)
{
alfa += uhel;
}
}
}Offline

Nerozumím tomu, jak chceš, aby se ti had pohyboval všemi směry a zároveň vše bylo ve čtvercové síti.
Offline

No na kód jsem se díval a stále platí, že nechápu, jak to chceš udělat. Můžeš sem dát funkční kód jak jsi to měl se čtyřmi směry, než jsi to začal upravovat?
Offline
↑ BrozekP: Jojo. Pozměním jenom ten switch, kterej bere direction a bude to funkční.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Snake
{
public partial class Form1 : Form
{
List <Food> seznamJidla = new List<Food>();
List<Form1> seznamBodu = new List<Form1>();
Graphics g;
Random nahodneJidlo;
string direction;
int prictiBod = 0;
float alfa;
int x;
int y;
public Form1()
{
InitializeComponent();
g = CreateGraphics();
nahodneJidlo = new Random();
}
private void Form1_Load(object sender, EventArgs e)
{
Timer timer = new Timer();
timer.Start();
timer.Interval = 5;
timer.Tick += new EventHandler(timer_Tick);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left: direction = "left"; break;
case Keys.Right: direction = "right"; break;
case Keys.Down: direction = "down"; break;
case Keys.Up: direction = "up"; break;
}
}
void timer_Tick(object sender, EventArgs e)
{
switch (direction)
{
case "left": x -= 1; break;
case "right": x += 1; break;
case "down": y += 1; break;
case "up": y -= 1; break;
}
label1.Text = x.ToString();
label4.Text = y.ToString();
kresliHada();
}
public void kresliHada()
{
Rectangle re = new Rectangle(x, y, 8, 8);
g.FillRectangle(Brushes.BlueViolet, re);
}
public void vygenerujJidlo()
{
seznamJidla.Add(new Food(nahodneJidlo.Next(0,ClientRectangle.Width),nahodneJidlo.Next(0, ClientRectangle.Height)));
foreach(Food f in seznamJidla)
{
g.DrawRectangle(new Pen(Color.Green), x, y, 200, 200);
label7.Text = f.Xova.ToString();
label8.Text = f.Yova.ToString();
}
}
public void naraziNaJidlo()
{
foreach (Food f2 in seznamJidla)
{
if ((f2.Xova == x) && (f2.Yova == y))
{
prictiBod++;
vygenerujJidlo();
}
}
}
public void jdi(float krok)
{
x += (int)(krok * Math.Sin(alfa));
y += (int)(krok * Math.Cos(alfa));
}
public void otocSe(float uhel)
{
alfa += uhel;
}
}
}Offline

Můžeš mi prosim poslat celý projekt? Ať si to můžu spustit. Měl bys ode mně mít oznámení na ICQ.
Offline