Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.79/29: Рейтинг темы: голосов - 29, средняя оценка - 4.79
1 / 1 / 0
Регистрация: 06.10.2014
Сообщений: 94
1

Движение, поворот и выстрелы танка

04.07.2015, 20:12. Показов 5755. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
На форме есть Rectangle, изображенный картинкой(Танк), Rectangle перемещается по нажатию клавиш(w,a,s,d), мне нужно чтобы картинка поворачивалась в сторону движения. Также хотелось бы узнать, каким образом можно реализовать выстрелы, так чтобы они летели в сторону направления картинки.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
namespace WindowsFormsApplication5
{
    public partial class Form1 : Form
    {
        Rectangle tank;
        Rectangle mause;
        
        
        public Form1()
        {
            InitializeComponent();
            DoubleBuffered = true;
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            tank = new Rectangle(50, 50, 50, 50);
            mause.Size = new Size(1,1);
        }
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            Invalidate();
            if (e.KeyData == Keys.W)
            {
                tank.Y -= 3;
                
            }
            if (e.KeyCode == Keys.S)
            {
                tank.Y += 3;
            }
            if (e.KeyCode == Keys.D)
            {
                tank.X += 3;
            }
            if (e.KeyCode == Keys.A)
            {
                tank.X -= 3;
            }
        }
 
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(Properties.Resources.Tank, tank);
        }
        
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.07.2015, 20:12
Ответы с готовыми решениями:

Движение танка в игре во время выстрела
пишу курсач на с#..игра танки. должен быть голый шарп, никаких XNA или подобного. начал и сразу...

Поворот башни танка за вектором мыши
Привет, форумчане. Необходимо сделать, чтобы башня у танка поворачивалась за камерой с определённой...

Как сделать поворот башни и склонение орудия для танка?
Доброго времени! Не могу разобраться с проблемой поворота башни и склонением орудия для танчика. В...

Движение и повороты танка
Здравстуйте. Я пытаюсь сделать чтобы у меня ездил танк. Заметил, что если проехать вперед от...

15
Заблокирован
04.07.2015, 22:07 2
Цитата Сообщение от E_X_E Посмотреть сообщение
картинка поворачивалась в сторону движения
у объектов Image и Bitmap есть метод img/bmp.RotateFlip(RotateFlipType.XXX);
1
1 / 1 / 0
Регистрация: 06.10.2014
Сообщений: 94
04.07.2015, 22:29  [ТС] 3
Цитата Сообщение от MansMI Посмотреть сообщение
у объектов Image и Bitmap есть метод img/bmp.RotateFlip(RotateFlipType.XXX);
В данном случае Image лежит на Rectangle, как это в моем коде выглядеть будет, я просто пробую не выходит чет
0
Заблокирован
04.07.2015, 22:56 4
как-то так
C#
1
2
3
4
5
6
7
8
9
10
public partial class Form1 : Form
    {
        Rectangle tank = new Rectangle(50, 50, 50, 50);
        Rectangle mause;
        Image img = (Image)Properties.Resources.Tank.Clone();
................................
private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(img, tank);
        }
1
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
04.07.2015, 23:56 5
E_X_E,
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
/// (C) Storm23, 2015
 
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace WindowsFormsApplication300
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
 
            BackgroundImage = (Bitmap)Image.FromStream(new WebClient().OpenRead("http://radakan.googlecode.com/svn/branches/old/own_smart_pointers/data/texture/splatting_grass.png"));
            
 
            new Game();
            MinimumSize = Game.Instance.FieldSize;
        }
 
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
 
            Game.MousePosition = PointToClient(MousePosition);
            Game.MouseButtons = MouseButtons;
 
            Game.Instance.Update();
            Game.Instance.Draw(e.Graphics);
            Invalidate();
        }
    }
 
    [Serializable]
    internal class Game
    {
        public static Game Instance { get; private set; }
        public static Random rnd = new Random(1);
        public Size FieldSize = new Size(800, 800);
        public List<GameItem> Items = new List<GameItem>();
        public Tank PlayerTank { get; set; }
        public static bool DebugMode { get; set; }
        public static Point MousePosition { get; set; }
        public static MouseButtons MouseButtons { get; set; }
 
        public Game()
        {
            Instance = this;
 
            //создаем танк игрока
            PlayerTank = new PlayerTank();
 
            //создаем танки противника
            new TankAI();
            new TankAI();
 
            //создаем камни
            new Stone();
            new Stone();
            new Stone();
            new Stone();
            new Stone();
            new Stone();
 
            //режим  отладки
            Game.DebugMode = false;
        }
 
        internal void Update()
        {
            var dt = 0.3f;
 
            foreach (var item in Items.ToList())
                item.Update(dt);
 
            new Collider().Update();
        }
 
        internal void Draw(Graphics gr)
        {
            foreach (var item in Items)
                item.Draw(gr);
        }
 
        public PointF GetRndPoint()
        {
            return new PointF(rnd.Next(FieldSize.Width - 40), rnd.Next(FieldSize.Height - 40));
        }
    }
 
    //базовый класс для игровых объектов
    [Serializable]
    abstract class GameItem
    {
        public abstract void Draw(Graphics gr);
        public PointF Location { get; set;}
        public int Radius { get; protected set; }
        public virtual void Update(float dt){;}
        public float Mass { get; set; }
        public virtual void OnCoollide(GameItem otherItem){;}
 
        public GameItem()
        {
            Game.Instance.Items.Add(this);
        }
 
        public void Remove()
        {
            Game.Instance.Items.Remove(this);
        }
    }
 
    //танк
    [Serializable]
    class Tank : GameItem
    {
        public PointF Velocity { get; set; }
        public PointF TowerDirection { get; set; }
        public virtual float MaxSpeed { get; protected set; }
        public bool IsDead { get; set; }
 
        public Tank()
        {
            Location = Game.Instance.GetRndPoint();
            Radius = 25;
            MaxSpeed = 5f;
            Mass = 50;
        }
        
        public override void Update(float dt)
        {
            if(!IsDead)
                Location = new PointF(Location.X + Velocity.X * dt, Location.Y + Velocity.Y * dt);
        }
 
        public override void Draw(Graphics gr)
        {
            //корпус
            var url = "http://********************/image/01201112/25f36bffa9ce1a60b97c42dc7a10d44e.png";
            var img = ImageCache.GetImage(url, new Size(100, 80));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.RotateTransform(180 + 180 * (float)(Math.Atan2(Velocity.Y, Velocity.X) / Math.PI));
            gr.DrawImage(img, -50, -40);
 
            //башня
            url = "http://********************/image/01201112/57e8dab7128aa7e3a9d4cf4b05a085b2.png";
            img = ImageCache.GetImage(url, new Size(100, 80));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.RotateTransform(180 + 180 * (float)(Math.Atan2(TowerDirection.Y, TowerDirection.X) / Math.PI));
            gr.DrawImage(img, -50, -40);
 
            if(IsDead)
            {
                url = "http://www.rw-designer.com/rsrc/wizard-fire.png";
                img = ImageCache.GetImage(url, new Size(50, 50));
                gr.DrawImage(img, -25, -25);
            }
 
            if(Game.DebugMode)
                gr.DrawEllipse(Pens.Red, -Radius, -Radius, 2*Radius, 2*Radius);
        }
 
        [NonSerialized]
        private DateTime lastFireTime;
 
        //сделать выстрел
        public void Fire()
        {
            if ((DateTime.Now - lastFireTime).TotalMilliseconds < 500)
                return;
 
            if (IsDead)
                return;
 
            var speed = 10;
            var l = TowerDirection.Distance(PointF.Empty);
            var dir = new PointF(TowerDirection.X / l, TowerDirection.Y / l);
            var v = new PointF(speed * dir.X, speed * dir.Y);
            var bullet = new Bullet(){Velocity = v};
            var pad = (Radius + bullet.Radius + 5);
            bullet.Location = new PointF(Location.X + dir.X * pad, Location.Y + dir.Y * pad);
            lastFireTime = DateTime.Now;
        }
    }
 
    //танк под управлением ИИ
    [Serializable]
    class TankAI : Tank
    {
        private PointF targetPoint;
        private float timeToChangeTargetPoint;   
 
        public override void  Update(float dt)
        {
            timeToChangeTargetPoint -= dt;
            if (timeToChangeTargetPoint < 0 || targetPoint.Distance(Location) < Radius)
            {
                //меняем направление движения
                targetPoint = Game.Instance.GetRndPoint();
                timeToChangeTargetPoint = 150;
 
                var d = new PointF(targetPoint.X - Location.X, targetPoint.Y - Location.Y);
                var l = d.Distance(PointF.Empty);
 
                Velocity = new PointF(MaxSpeed*d.X/l, MaxSpeed*d.Y/l);
            }
 
            //башня - на игрока
            var p = Game.Instance.PlayerTank.Location;
            TowerDirection = new PointF(p.X - Location.X, p.Y - Location.Y);
 
            //стреляем постоянно
            if(!Game.Instance.PlayerTank.IsDead)
            if(Game.rnd.Next(300) == 1)
                Fire();
 
            base.Update(dt);
        }
 
        public override void OnCoollide(GameItem otherItem)
        {
            if (otherItem == null || otherItem.Mass >= Mass)
                timeToChangeTargetPoint = 0;
            base.OnCoollide(otherItem);
        }
    }
 
    //танк игрока
    [Serializable]
    class PlayerTank : Tank
    {
        private float Angle { set; get; }
 
        public override void Update(float dt)
        {
            var speed = 0.01f;
 
            if (Keyboard.IsKeyDown(Keys.D)) Angle += 0.05f * dt;
            if (Keyboard.IsKeyDown(Keys.A)) Angle -= 0.05f * dt;
            if (Keyboard.IsKeyDown(Keys.S)) speed = -MaxSpeed;
            if (Keyboard.IsKeyDown(Keys.W)) speed = MaxSpeed;
 
            Velocity = new PointF(speed * (float)Math.Cos(Angle), speed * (float)Math.Sin(Angle));
 
            //башня
            TowerDirection = new PointF(Game.MousePosition.X - Location.X, Game.MousePosition.Y - Location.Y);
 
            //выстрел
            if (Game.MouseButtons == MouseButtons.Left)
                Fire();
 
            base.Update(dt);
        }
    }
 
    //камень
    [Serializable]
    class Stone : GameItem
    {
        public Stone()
        {
            Location = Game.Instance.GetRndPoint();
            Radius = 25;
            Mass = 100;
        }
 
        public override void Draw(Graphics gr)
        {
            //камень
            var url = "http://www.typoberlin.de/2011/img/game/6041_Stone.png";
            var img = ImageCache.GetImage(url, new Size(100, 100));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.DrawImage(img, -50, -50);
 
            if (Game.DebugMode)
                gr.DrawEllipse(Pens.Red, -Radius, -Radius, 2 * Radius, 2 * Radius);
        }
    }
 
    //снаряд
    [Serializable]
    class Bullet : GameItem
    {
        public PointF Velocity { get; set; }
 
        public Bullet()
        {
            Radius = 3;
        }
 
        public override void Draw(Graphics gr)
        {
            var url = "http://www.1000yards.net/forum/Themes/default/images/bullet.png";
            var img = ImageCache.GetImage(url, new Size(6, 14));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.RotateTransform(90 + 180 * (float)(Math.Atan2(Velocity.Y, Velocity.X) / Math.PI));
            gr.DrawImage(img, -3, -7);
 
            if (Game.DebugMode)
                gr.DrawEllipse(Pens.Red, -Radius, -Radius, 2 * Radius, 2 * Radius);
        }
 
        public override void Update(float dt)
        {
            Location = new PointF(Location.X + Velocity.X * dt, Location.Y + Velocity.Y * dt);
        }
 
        public override void OnCoollide(GameItem otherItem)
        {
            Remove();
 
            if (otherItem is Tank)//капец танку
                (otherItem as Tank).IsDead = true;
        }
    }
 
    //коллайдер
    class Collider
    {
        public void Update()
        {
            var items = Game.Instance.Items.ToList();
 
            for (int i = 0; i < items.Count; i++)
            for (int j = i + 1; j < items.Count; j++)
            {
                var p1 = items[i].Location;
                var p2 = items[j].Location;
                var d = p1.Distance(p2);
                var overlap = items[i].Radius + items[j].Radius - d;
                if (overlap > 0)
                {
                    //столкновение
                    var dir = new PointF(p1.X - p2.X, p1.Y - p2.Y);
                    if (items[i].Mass > items[j].Mass)
                        items[j].Location = new PointF(p2.X - dir.X * overlap, p2.Y - dir.Y * overlap);
                    else
                        items[i].Location = new PointF(p1.X + dir.X * overlap, p1.Y + dir.Y * overlap);
                    //
                    items[i].OnCoollide(items[j]);
                    items[j].OnCoollide(items[i]);
                }
            }
 
            for (int i = 0; i < items.Count; i++)
            {
                var p = items[i].Location;
                if (p.X < 0) p.X = 0;
                if (p.X > Game.Instance.FieldSize.Width) p.X = Game.Instance.FieldSize.Width;
                if (p.Y < 0) p.Y = 0;
                if (p.Y > Game.Instance.FieldSize.Height) p.Y = Game.Instance.FieldSize.Height;
                if(p != items[i].Location)
                {
                    //столкновение со стеной
                    items[i].Location = p;
                    items[i].OnCoollide(null);
                }
            }
        }
    }
 
 
    //кеш изображений
    static class ImageCache
    {
        private static Dictionary<string, Bitmap> cache = new Dictionary<string, Bitmap>();
 
        public static Bitmap GetImage(string url, Size size)
        {
            Bitmap img;
            if (!cache.TryGetValue(url, out img))
            {
                cache[url] = img = (Bitmap)Image.FromStream(new WebClient().OpenRead(url)).GetThumbnailImage(size.Width, size.Height, null, IntPtr.Zero);
                img.SetResolution(96, 96);
            }
 
            return img;
        }
    }
 
    //хелпер
    static class PointHelper
    {
        public static float Distance(this PointF p1, PointF p2)
        {
            var dx = p1.X - p2.X;
            var dy = p1.Y - p2.Y;
            return (float)Math.Sqrt(dx * dx + dy * dy);
        }
    }
 
    //клавиатура
    public static class Keyboard
    {
        [Flags]
        private enum KeyStates
        {
            None = 0,
            Down = 1,
            Toggled = 2
        }
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern short GetKeyState(int keyCode);
 
        private static KeyStates GetKeyState(Keys key)
        {
            KeyStates state = KeyStates.None;
 
            short retVal = GetKeyState((int)key);
 
            if ((retVal & 0x8000) == 0x8000)
                state |= KeyStates.Down;
 
            if ((retVal & 1) == 1)
                state |= KeyStates.Toggled;
 
            return state;
        }
 
        public static bool IsKeyDown(Keys key)
        {
            return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
        }
 
        public static bool IsKeyToggled(Keys key)
        {
            return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
        }
    }
}


Движение, поворот и выстрелы танка


Немножко сложновато получилось, но ничего не поделаешь, игры они простыми не бывают
2
1 / 1 / 0
Регистрация: 06.10.2014
Сообщений: 94
05.07.2015, 00:14  [ТС] 6
Цитата Сообщение от MansMI Посмотреть сообщение
как-то так
C#
1
2
3
4
5
6
7
8
9
10
public partial class Form1 : Form
    {
        Rectangle tank = new Rectangle(50, 50, 50, 50);
        Rectangle mause;
        Image img = (Image)Properties.Resources.Tank.Clone();
................................
private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(img, tank);
        }
В событие Key_Down развернуть картинку не получается, а в событие Form_Paint не варик использовать клавиши с клавиатуры, я понял как разворачивать, я не понимаю как заставить его это делать по нажатию клавишии

Добавлено через 7 минут
Немножко сложновато получилось, но ничего не поделаешь, игры они простыми не бывают [/QUOTE]

Сложновато не то слово))) а можно описать что а классе PlayerTank?
0
Заблокирован
05.07.2015, 00:16 7
нужно хранить текущее направление танка и исходя из него и клавиши img.RotateFlip(RotateFlipType.XXX); поворачивать +-90 или 180
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
05.07.2015, 00:35 8
Лучший ответ Сообщение было отмечено Ev_Hyper как решение

Решение

Цитата Сообщение от E_X_E Посмотреть сообщение
а можно описать что а классе PlayerTank?
А что там не понятно? Это кажется самый маленький класс.

Вот исправил баги и доработал немного:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
/// (C) Storm23, 2015
 
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace WindowsFormsApplication300
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
 
            BackgroundImage = (Bitmap)Image.FromStream(new WebClient().OpenRead("http://radakan.googlecode.com/svn/branches/old/own_smart_pointers/data/texture/splatting_grass.png"));
 
            Text = "Tanks";
 
            new Game();
            MinimumSize = Game.Instance.FieldSize;
        }
 
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
 
            Game.MousePosition = PointToClient(MousePosition);
            Game.MouseButtons = MouseButtons;
 
            Game.Instance.Update();
            Game.Instance.Draw(e.Graphics);
 
            if (Game.Instance.PlayerTank.IsDead)
            {
                e.Graphics.ResetTransform();
                e.Graphics.DrawString("Press Space to new Game", Font, Brushes.White, 0, 0);
            }
 
            Invalidate();
        }
 
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyData == Keys.Space)
                new Game();
        }
    }
 
    [Serializable]
    internal class Game
    {
        public static Game Instance { get; private set; }
        public static Random rnd = new Random();
        public Size FieldSize = new Size(800, 800);
        public List<GameItem> Items = new List<GameItem>();
        public Tank PlayerTank { get; set; }
        public static bool DebugMode { get; set; }
        public static Point MousePosition { get; set; }
        public static MouseButtons MouseButtons { get; set; }
 
        public Game()
        {
            Instance = this;
 
            //создаем камни
            new Stone();
            new Stone();
            new Stone();
            new Stone();
            new Stone();
            new Stone();
 
            //создаем танк игрока
            PlayerTank = new PlayerTank();
 
            //создаем танки противника
            new TankAI();
            new TankAI();
 
            //режим  отладки
            Game.DebugMode = false;
        }
 
        internal void Update()
        {
            var dt = 0.3f;
 
            foreach (var item in Items.ToList())
                item.Update(dt);
 
            new Collider().Update();
        }
 
        internal void Draw(Graphics gr)
        {
            foreach (var item in Items)
                item.Draw(gr);
        }
 
        public PointF GetRndPoint()
        {
            return new PointF(rnd.Next(FieldSize.Width - 40), rnd.Next(FieldSize.Height - 40));
        }
    }
 
    //базовый класс для игровых объектов
    [Serializable]
    abstract class GameItem
    {
        public abstract void Draw(Graphics gr);
        public PointF Location { get; set;}
        public int Radius { get; protected set; }
        public virtual void Update(float dt){;}
        public float Mass { get; set; }
        public virtual void OnCoollide(GameItem otherItem){;}
 
        public GameItem()
        {
            Game.Instance.Items.Add(this);
        }
 
        public void Remove()
        {
            Game.Instance.Items.Remove(this);
        }
    }
 
    //танк
    [Serializable]
    class Tank : GameItem
    {
        public PointF Velocity { get; set; }
        public PointF TowerDirection { get; set; }
        public virtual float MaxSpeed { get; protected set; }
        public bool IsDead { get; set; }
 
        public Tank()
        {
            Location = Game.Instance.GetRndPoint();
            Radius = 25;
            MaxSpeed = 5f;
            Mass = 50;
        }
        
        public override void Update(float dt)
        {
            if(!IsDead)
                Location = new PointF(Location.X + Velocity.X * dt, Location.Y + Velocity.Y * dt);
        }
 
        public override void Draw(Graphics gr)
        {
            //корпус
            var url = "http://********************/image/01201112/25f36bffa9ce1a60b97c42dc7a10d44e.png";
            var img = ImageCache.GetImage(url, new Size(100, 80));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.RotateTransform(180 + 180 * (float)(Math.Atan2(Velocity.Y, Velocity.X) / Math.PI));
            gr.DrawImage(img, -50, -40);
 
            //башня
            url = "http://********************/image/01201112/57e8dab7128aa7e3a9d4cf4b05a085b2.png";
            img = ImageCache.GetImage(url, new Size(100, 80));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.RotateTransform(180 + 180 * (float)(Math.Atan2(TowerDirection.Y, TowerDirection.X) / Math.PI));
            gr.DrawImage(img, -50, -40);
 
            if(IsDead)
            {
                url = "http://www.rw-designer.com/rsrc/wizard-fire.png";
                img = ImageCache.GetImage(url, new Size(50, 50));
                gr.DrawImage(img, -25, -25);
            }
 
            if(Game.DebugMode)
                gr.DrawEllipse(Pens.Red, -Radius, -Radius, 2*Radius, 2*Radius);
        }
 
        [NonSerialized]
        private DateTime lastFireTime;
 
        //сделать выстрел
        public void Fire()
        {
            if ((DateTime.Now - lastFireTime).TotalMilliseconds < 500)
                return;
 
            if (IsDead)
                return;
 
            var speed = 10;
            var l = TowerDirection.Distance(PointF.Empty);
            var dir = new PointF(TowerDirection.X / l, TowerDirection.Y / l);
            var v = new PointF(speed * dir.X, speed * dir.Y);
            var bullet = new Bullet(){Velocity = v};
            var pad = (Radius + bullet.Radius + 5);
            bullet.Location = new PointF(Location.X + dir.X * pad, Location.Y + dir.Y * pad);
            lastFireTime = DateTime.Now;
        }
    }
 
    //танк под управлением ИИ
    [Serializable]
    class TankAI : Tank
    {
        private PointF targetPoint;
        private float timeToChangeTargetPoint;   
 
        public override void  Update(float dt)
        {
            
            timeToChangeTargetPoint -= dt;
 
            if (!IsDead)
            if (timeToChangeTargetPoint < 0 || targetPoint.Distance(Location) < Radius)           
            {
                //меняем направление движения
                targetPoint = Game.Instance.GetRndPoint();
                timeToChangeTargetPoint = 150;
 
                var d = new PointF(targetPoint.X - Location.X, targetPoint.Y - Location.Y);
                var l = d.Distance(PointF.Empty);
 
                Velocity = new PointF(MaxSpeed*d.X/l, MaxSpeed*d.Y/l);
            }
 
            //башня - на игрока
            var p = Game.Instance.PlayerTank.Location;
            TowerDirection = new PointF(p.X - Location.X, p.Y - Location.Y);
 
            //стреляем постоянно
            if(!Game.Instance.PlayerTank.IsDead)
            if(Game.rnd.Next(300) == 1)
                Fire();
 
            base.Update(dt);
        }
 
        public override void OnCoollide(GameItem otherItem)
        {
            if (otherItem == null || otherItem.Mass >= Mass)
                timeToChangeTargetPoint = 0;
            base.OnCoollide(otherItem);
        }
    }
 
    [Serializable]
    class PlayerTank : Tank
    {
        private float Angle { set; get; }
 
        public override void Update(float dt)
        {
            var speed = 0.01f;
 
            if (Keyboard.IsKeyDown(Keys.D)) Angle += 0.05f * dt;
            if (Keyboard.IsKeyDown(Keys.A)) Angle -= 0.05f * dt;
            if (Keyboard.IsKeyDown(Keys.S)) speed = -MaxSpeed;
            if (Keyboard.IsKeyDown(Keys.W)) speed = MaxSpeed;
 
            Velocity = new PointF(speed * (float)Math.Cos(Angle), speed * (float)Math.Sin(Angle));
 
            //башня
            TowerDirection = new PointF(Game.MousePosition.X - Location.X, Game.MousePosition.Y - Location.Y);
 
            //выстрел
            if (Game.MouseButtons == MouseButtons.Left)
                Fire();
 
            base.Update(dt);
        }
 
        public override void Draw(Graphics gr)
        {
            gr.ResetTransform();
            using (var brush = new SolidBrush(Color.FromArgb(20, Color.Lime)))
            {
                var r = Radius*2;
                gr.FillEllipse(brush, Location.X - r, Location.Y - r, 2*r, 2*r);
            }
 
            base.Draw(gr);
        }
    }
 
    //камень
    [Serializable]
    class Stone : GameItem
    {
        public Stone()
        {
            Location = Game.Instance.GetRndPoint();
            Radius = 25;
            Mass = 100;
        }
 
        public override void Draw(Graphics gr)
        {
            //камень
            var url = "http://www.typoberlin.de/2011/img/game/6041_Stone.png";
            var img = ImageCache.GetImage(url, new Size(100, 100));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.DrawImage(img, -50, -50);
 
            if (Game.DebugMode)
                gr.DrawEllipse(Pens.Red, -Radius, -Radius, 2 * Radius, 2 * Radius);
        }
    }
 
    //снаряд
    [Serializable]
    class Bullet : GameItem
    {
        public PointF Velocity { get; set; }
 
        public Bullet()
        {
            Radius = 3;
        }
 
        public override void Draw(Graphics gr)
        {
            var url = "http://www.1000yards.net/forum/Themes/default/images/bullet.png";
            var img = ImageCache.GetImage(url, new Size(6, 14));
            gr.ResetTransform();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.RotateTransform(90 + 180 * (float)(Math.Atan2(Velocity.Y, Velocity.X) / Math.PI));
            gr.DrawImage(img, -3, -7);
 
            if (Game.DebugMode)
                gr.DrawEllipse(Pens.Red, -Radius, -Radius, 2 * Radius, 2 * Radius);
        }
 
        public override void Update(float dt)
        {
            Location = new PointF(Location.X + Velocity.X * dt, Location.Y + Velocity.Y * dt);
        }
 
        public override void OnCoollide(GameItem otherItem)
        {
            Remove();
 
            if (otherItem is Tank)//капец танку
                (otherItem as Tank).IsDead = true;
        }
    }
 
    //коллайдер
    class Collider
    {
        public void Update()
        {
            var items = Game.Instance.Items.ToList();
 
            for (int i = 0; i < items.Count; i++)
            for (int j = i + 1; j < items.Count; j++)
            {
                var p1 = items[i].Location;
                var p2 = items[j].Location;
                var d = p1.Distance(p2);
                var overlap = items[i].Radius + items[j].Radius - d;
                if (overlap > 0)
                {
                    //столкновение
                    var dir = new PointF(p1.X - p2.X, p1.Y - p2.Y);
                    var l = dir.Distance(PointF.Empty);
                    if (items[i].Mass > items[j].Mass)
                        items[j].Location = new PointF(p2.X - dir.X * overlap / l, p2.Y - dir.Y * overlap / l);
                    else
                        items[i].Location = new PointF(p1.X + dir.X * overlap / l, p1.Y + dir.Y * overlap / l);
                    //
                    items[i].OnCoollide(items[j]);
                    items[j].OnCoollide(items[i]);
                }
            }
 
            for (int i = 0; i < items.Count; i++)
            {
                var p = items[i].Location;
                if (p.X < 0) p.X = 0;
                if (p.X > Game.Instance.FieldSize.Width) p.X = Game.Instance.FieldSize.Width;
                if (p.Y < 0) p.Y = 0;
                if (p.Y > Game.Instance.FieldSize.Height) p.Y = Game.Instance.FieldSize.Height;
                if(p != items[i].Location)
                {
                    //столкновение со стеной
                    items[i].Location = p;
                    items[i].OnCoollide(null);
                }
            }
        }
    }
 
 
    //кеш изображений
    static class ImageCache
    {
        private static Dictionary<string, Bitmap> cache = new Dictionary<string, Bitmap>();
 
        public static Bitmap GetImage(string url, Size size)
        {
            Bitmap img;
            if (!cache.TryGetValue(url, out img))
            {
                cache[url] = img = (Bitmap)Image.FromStream(new WebClient().OpenRead(url)).GetThumbnailImage(size.Width, size.Height, null, IntPtr.Zero);
                img.SetResolution(96, 96);
            }
 
            return img;
        }
    }
 
    //хелпер
    static class PointHelper
    {
        public static float Distance(this PointF p1, PointF p2)
        {
            var dx = p1.X - p2.X;
            var dy = p1.Y - p2.Y;
            return (float)Math.Sqrt(dx * dx + dy * dy);
        }
    }
 
    //клавиатура
    public static class Keyboard
    {
        [Flags]
        private enum KeyStates
        {
            None = 0,
            Down = 1,
            Toggled = 2
        }
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern short GetKeyState(int keyCode);
 
        private static KeyStates GetKeyState(Keys key)
        {
            KeyStates state = KeyStates.None;
 
            short retVal = GetKeyState((int)key);
 
            if ((retVal & 0x8000) == 0x8000)
                state |= KeyStates.Down;
 
            if ((retVal & 1) == 1)
                state |= KeyStates.Toggled;
 
            return state;
        }
 
        public static bool IsKeyDown(Keys key)
        {
            return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
        }
 
        public static bool IsKeyToggled(Keys key)
        {
            return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
        }
    }
}


Движение, поворот и выстрелы танка
2
1 / 1 / 0
Регистрация: 06.10.2014
Сообщений: 94
05.07.2015, 05:50  [ТС] 9
Пацаны вы извините за то что я туплю, я на практике 1 курс, задание такое, надо написать игру Батл сити на с#. Я начал делать танк, сделал Rectangle на него кинул картинку, сделал так чтобы Rectangle перемещался по клавишам, но передо мной стоит проблема, я пока не представляю как определять перед или зад, и еще как сделать так чтобы картинка разворачивалась в сторону направления. Надеюсь вы подскажите как это делается, или если нет подскажите как можно более умно сделать танк
0
Заблокирован
05.07.2015, 06:14 10
Пацан, выложи тут свой Tank.bmp/png/jpg
0
1 / 1 / 0
Регистрация: 06.10.2014
Сообщений: 94
05.07.2015, 07:32  [ТС] 11
Цитата Сообщение от MansMI Посмотреть сообщение
Пацан, выложи тут свой Tank.bmp/png/jpg
Название: 588ec8e5493c.png
Просмотров: 288

Размер: 747 байт
0
Заблокирован
05.07.2015, 08:55 12
Лучший ответ Сообщение было отмечено E_X_E как решение

Решение

если на picBox рисовать мерцания не будет
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  public partial class Form1 : Form
    {
        TANK myTank=new TANK(0,0);
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            int dX = 0, dY = 0;
            if (e.KeyCode == Keys.Escape)
            {
                Close();
                return;
            }
            if (e.KeyCode == Keys.W)
                if (myTank.dir != 0) myTank.dir = 0;
                else dY = -3; 
            if (e.KeyCode == Keys.A)
                if (myTank.dir != 1)
                {
                    myTank.dir = 1;
                    myTank.rt = RotateFlipType.Rotate270FlipNone;
                }
                else dX = -3;
            if (e.KeyCode == Keys.S)
                if (myTank.dir != 2)
                {
                    myTank.dir = 2;
                    myTank.rt = RotateFlipType.Rotate180FlipNone;
                }
                else dY = 3;
            if(e.KeyCode==Keys.D)
                if (myTank.dir != 3)
                {
                    myTank.dir = 3;
                    myTank.rt = RotateFlipType.Rotate90FlipNone;
                }
                else dX = 3;
            myTank.Move(dX, dY, ClientRectangle);
            Picture();
        }
 
        void Picture()
        {
            Bitmap bmp = (Bitmap)Properties.Resources.Tank;
            if (myTank.dir > 0) bmp.RotateFlip(myTank.rt);
            //bmp.MakeTransparent(Color.White);
            using (Graphics g = CreateGraphics())
            {
                g.Clear(Color.White);
                g.DrawImage(bmp, myTank.rec);
            }
        }
 
        private void Form1_Shown(object sender, EventArgs e)
        {
            Picture();
        }
    }
 
    public class TANK
    {
        public Rectangle rec;
        public int dir;
        public RotateFlipType rt;
        public TANK(int x, int y)
        {
            rec = new Rectangle(x, y, 50, 50);
            dir = 0;
        }
        public void Move(int dX, int dY, Rectangle crec)
        {
            if (rec.X + dX >= 0 && rec.Right + dX < crec.Width &&
                rec.Y + dY >= 0 && rec.Bottom + dY < crec.Height)
            {
                rec.X += dX;
                rec.Y += dY;
            }
        }
    }
1
1 / 1 / 0
Регистрация: 06.10.2014
Сообщений: 94
06.07.2015, 06:19  [ТС] 13
Прошу прощения еще раз, понимаю надоел, опишите как вы реализовали движение(не код) а предназначение полей, в особенности dir
0
Заблокирован
06.07.2015, 06:30 14
C#
1
2
3
        public Rectangle rec;//прямоугольник рисования
        public int dir;//направление движения 0-3
        public RotateFlipType rt;//тип поворота
1
Заблокирован
11.07.2015, 09:59 15
как там практика? постреляй пробелом
Вложения
Тип файла: rar Tank.rar (8.6 Кб, 89 просмотров)
0
1 / 1 / 0
Регистрация: 06.10.2014
Сообщений: 94
12.07.2015, 20:12  [ТС] 16
Цитата Сообщение от MansMI Посмотреть сообщение
как там практика? постреляй пробелом
Блин супер. Я до сих пор бьюсь не могу сделать, а можно код посмотреть?

Добавлено через 13 часов 8 минут
Цитата Сообщение от MansMI Посмотреть сообщение
как там практика? постреляй пробелом
Да и вражеские танки. Блин скинь код прошу))
0
12.07.2015, 20:12
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.07.2015, 20:12
Помогаю со студенческими работами здесь

Движение танка. Как уменьшить код?
Задача: Танк в компьютерной игре может двигаться в одном из четырех направлений, обозначим их...

Поворот и движение
1. spriteBatch.Begin(); spriteBatch.Draw(panzerDummy, panzerDummyVector,...

Поворот и движение
Делаю ездящее тело(танк). Управление как в привычных всем гонках. Налево держишь-поворачивает...

Движение персонажа и поворот при изменении направления.
Здравствуйте! AS 2.0 В игре есть персонаж, который двигается по клику мыши. Необходимо сделать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru