Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

protected override void Dispose(bool disposing) {

if(teapotTexture!= null)

teapotTexture. Dispose();

foreach(Mesh m in objects)

…;

}

9.5. В качестве имени файла с текстурой была указана строка “spheremap. bmp”. Для того, чтобы приложение нашло этот файл скопируйте его в корневой каталог проекта (где лежит файл DXApp. sln).

Установите этот каталог в качестве текущего каталога для запуска приложения. Для этого в окне Solution Explorer нажмите правую кнопку мыши над элементом с именем проекта (в нашем случае это DXApp). В появившемся меню выберите пункт Properties.

На экране появится окно свойств проекта. В расположенном слева иерархическом списке выберите раздел Configuration properties/Debugging, в расположенном справа списке установите в свойстве Working directory укажите корневой каталог проекта.

9.4. Созданная средствами Direct3D модель чайника не содержит координат текстуры. Поэтому текстурные координаты будут вычисляться исходя их вектора нормали по следующим формулам

что создает иллюзию отражающей поверхности.

В методе Form1_Paint непосредственно перед рисованием чайника добавьте код, включающий текстурирование и устанавливающий соответствующие режимы текстурирования. Не забудьте выключить текстурирование перед рисованием вращающихся вокруг чайника сфер.

private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) {

// Выключаем текстурирование

d3d.SetTexture(0,null);

int numObjects = objects. Length;

for(int i = 0;i<numObjects;i++) {

}

// В качестве текстурных координат берем вектор нормали

d3d.TextureState[0].TextureCoordinateIndex =

(int)TextureCoordinateIndex.CameraSpaceNormal;

// Преобразуем текстурные координаты по заданным формулам

d3d. Transform. Texture0 = Matrix. Scaling(0.5f,-0.5f,1.0f)*

Matrix. Translation(0.5f,0.5f,0.0f);

// Передаем блоку растеризации две текстурные координаты

d3d. TextureState[0].TextureTransform = TextureTransform. Count2;

// Устанавливаем текстурк

d3d. SetTexture(0,teapotTexture);

// Устанавливаем свойства материала и рисуем чайник

d3d. Material = teapotMaterial;

teapot. DrawSubset(0);

}

Главное окно приложения теперь должно выглядеть следующим образом.

НЕ нашли? Не то? Что вы ищете?

9.5. Если внимательно рассматривать полученное динамическое изображение, то можно заметить, что в некоторые моменты времени при некоторых положениях объекта на текстуре возникают явно заметные прямоугольные элементы. Для избавления от этого эффекта включите билинейную фильтрацию текстур, добавив следующий код перед рисованием чайника в методе Form1_Paint

private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) {

// Включаем билинейную фильтрацию текстур

d3d. SamplerState[0].MinFilter = TextureFilter. Linear;

d3d. SamplerState[0].MagFilter = TextureFilter. Linear;

teapot. DrawSubset(0);

}

Шаг 10. Добавляем фон.

10.1. На этом шаге к сцене будет добавлен фон. Или точнее, сцена вместе с наблюдателем будет помещена внутрь текстурированного тора. Добавьте к классу Form1 поля данных для хранения ссылок на тор и на текстуру для тора (аналогично полям данных для чайника и его текстуры).

сlass Form1 {

Mesh torus = null; // Тор, внутри которого находится наблюдатель

Texture torusTexture = null; // Текстура для тора

}

10.2. В метод Form1_Load добавьте код для создания полигональной модели тора и загрузки текстуры для него. Этот код также будет похож на код для создания модели чайника.

private void Form1_Load(object sender, System. EventArgs e) {

// Загружаем модель тора из файла с именем torus.x

torus = Mesh. FromFile("torus. x",

MeshFlags.Managed, // Область памяти для размещения геометрии

d3d);

// Загружаем текстуру для тора из файла с именем water.bmp

using(FileStream textureFile2 =

new FileStream("water. bmp",FileMode. Open)) {

torusTexture = Texture. FromStream(d3d,

textureFile2, // Поток данных с текстурой

0, // Будем использовать как обычную текстуру

Pool.Managed); // Область памяти для размещения текстуры

TextureFile2.Close();

}

}

Скопируйте в корневой каталог проекта файлы torus. x и water. bmp.

10.3. Точно также, как было сделано для модели чайника, ресурсы, занятые для модели и текстуры тора, необходимо освободить в методе Dispose.

protected override void Dispose(bool disposing) {

if(torusTexture!= null)

torusTexture. Dispose();

if(torus!= null)

torus. Dispose();

}

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

private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) {

teapot. DrawSubset(0);

// Устанавливаем преобразование координат для тора

d3d. Transform. World = Matrix. Scaling(10,10,10)*

Matrix. RotationZ((float)(Math. PI/2))*

Matrix. Translation(0,-12,0)*

Matrix. RotationX((float)(-Math. PI/6));

// Включаем свертку текстурных координат для правильного отображение

// текстурированного тора

d3d. RenderState. Wrap0 = WrapCoordinates. One|WrapCoordinates. Zero;

// Получаем текстурные координаты из данных модели

d3d.TextureState[0].TextureCoordinateIndex =

(int)TextureCoordinateIndex.PassThru;

// Устанавливаем текстуру для тора

d3d.SetTexture(0,torusTexture);

// Выключаем преобразование текстурных координат

d3d. TextureState[0].TextureTransform = TextureTransform. Disable;

// Выключаем расчет освещения

d3d. RenderState. Lighting = false;

// Рисуем тор

torus.DrawSubset(0);

// Включаем расчет освещения

d3d. RenderState. Lighting = true;

}

Внешний вид окна после выполнения шага 10 показан на следующем рисунке.

Шаг 11. Динамическое изменение фона.

11.1. На 9 шаге матрица преобразования текстурных координат использовалась для сдвига и масштабирования координат векторов нормалей. Разрешив преобразования текстурных координат для тора и изменяя матрицу преобразования текстурных координат можно добиться интересного эффекта движущегося фона.

В методе Form1_Paint добавьте следующий код вместо строки, в которой свойству TextureTransform присваивается значение TextureTransform. Disable.

private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) {

// Устанавливаем текстуру для тора

d3d. SetTexture(0,torusTexture);

// Вычисляем сдвиг текстурных координат

double deltaTex = totalSeconds*0.2;

// Приводим его к диапазону [0..1]

deltaTex -= Math.Floor(deltaTex);

// Задаем матрицу сдвига для двух текстурных координат

Matrix texMatrix = Matrix. Identity;

texMatrix. M31 = (float)-deltaTex;

texMatrix.M32 = (float)-deltaTex;

// Применяем матрицы для преобразования текстурных координат

d3d.Transform.Texture0 = texMatrix;

// Выключаем расчет освещения

d3d. RenderState. Lighting = false;

// Рисуем тор

torus. DrawSubset(0);

// Включаем расчет освещения

d3d. RenderState. Lighting = true;

}

После выполнения шага 11 фон в окне приложения должен начать двигаться (на следующем рисунке этого, к сожалению, не видно J)

Приложение 1. Обработчик события Button1_Click

switch(Next)

{

case 0:

removeouter = true;

middleTransparency = 1.0f;

removemiddle = false;

timer1.Enabled = true;

button1.Text = "Remove middle Layer";

break;

case 1:

removeouter = false;

removemiddle = true;

outerTransparency = 0.0f;

timer1.Enabled = true;

button1.Text = "Restore Layers";

break;

case 2:

removeouter = false;

removemiddle = false;

outerTransparency = 1.0f;

middleTransparency = 1.0f;

button1.Text = "Remove outer Layer";

Refresh();

break;

default:

timer1.Enabled = false;

break;

}

if(Next < 2)Next++;

else Next = 0;


Приложение 2. Код, выполняющийся при «тике» таймера

masterTransparency = Count;

if(Count > 0.05) Count -= 0.05f;

else

{

Count = 1.0f;

timer1.Enabled = false;

masterTransparency = 0.0f;

}

if(removeouter)

{

outerTransparency = masterTransparency;

}

if(removemiddle)

{

middleTransparency = masterTransparency;

}


Приложение 3. Код метода OnPaint

protected override void OnPaint(System. Windows. Forms. PaintEventArgs e)

{

// Draw the base image

e. Graphics. DrawImage(btmInner,

rect,

0,0, 600, 300,

GraphicsUnit. Pixel);

//Set alpha in the ColorMatrix

middleColorMatrix. Matrix33 = middleTransparency;

// Set color matrix of imageAttributes

middleImageAttributes. SetColorMatrix(middleColorMatrix,

ColorMatrixFlag. Default,

ColorAdjustType. Bitmap);

// Draw the middle image

e. Graphics. DrawImage(btmmiddle,

rect,

0,0, 600, 300,

GraphicsUnit. Pixel, middleImageAttributes);

//Set alpha in the ColorMatrix

outerColorMatrix. Matrix33 = outerTransparency;

// Set color matrix of imageAttributes

outerImageAttributes. SetColorMatrix(outerColorMatrix,

ColorMatrixFlag. Default,

ColorAdjustType. Bitmap);

// Draw the outer image

e. Graphics. DrawImage(btmouter,

rect,

0,0, 600, 300,

GraphicsUnit. Pixel, outerImageAttributes);

Лабораторная работа №5.
Создание сетевой многопользовательской игры на платформе. NET с применением технологии. NET Remoting

1. Создание оконного приложения.

Запустите интегрированную среду разработки Microsoft Visual 2003. Выберите пункт меню File/New/New Project.

В появившемся диалоговом окне в списке Project Types выберите пункт Visual C# Projects, в обновившемся списке Templates выберите пункт Windows Application. В поле ввода Name введите название проекта (например, MultiPlayer), в поле ввода Location укажите путь к каталогу проекта (например, С:\temp). Галочку напротив строки Create directory for new solution можно убрать.

После нажатия кнопки OK будет создан проект для оконного приложения. Для сборки проекта выберите пункт главного меню Build/Build Solution или нажмите Ctrl+Shift+B.

Сборка должна пройти без ошибок. Для выполнения программы выберите пункт меню Debug/Start Without Debugging или нажмите Ctrl+F5.

На экране появится окно вашего приложения.

2. Настройка свойств окна

В окне Solution Explorer отображается список файлов проекта. Исходный текст на языке C#, относящийся к главному окну приложения находится в файле Form1.cs. Нажатие над этим файлом правой кнопки мыши приводит к появлению контекстного меню, в котором присутствуют пункты View Code и View Designer, определяющие отображение в окне редактора или исходного текста или внешнего вида окна.

Нажмите правую кнопку мыши в свободной области редактора внешнего вида окна и в появившемся контекстном меню выберите пункт Properties.

На экране появится окно редактора свойств формы. Убедитесь, что третья слева кнопка, отображающая список свойств, нажата.

В свойствах окна (формы) измените свойство Text, задающее заголовок окна, на “Multiplayer Game”. Теперь окно приложения должно выглядеть следующим образом.

2. Добавление игровой логики.

Добавим в файл Form1.cs код, задающий правила игры. Разместите делегат ShowPlayerHandler и классы Player и Game после класса Form1, чтобы не нарушать работу визуального дизайнера. Фрагменты приведенного ниже исходного кода можно найти в файле scratch. cs под меткой 1. Здесь и далее жирным шрифтом выделен добавляемый исходный текст. Комментарии можно пропускать J.

namespace MultiPlayer {

public class Form1 : System. Windows. Forms. Form {

}

public delegate void ShowPlayerHandler(Player player, bool visible);

public class Player {

protected int x, y;

protected Game game; // Игра, в которой игрок участвует

public Player(Game g) {

game = g;

Random r = new Random();

x = 10 + r. Next(100); // Задаем случайные координаты

y = 10 + r. Next(100);

}

public int X {

get {

return x;

}

}

public int Y {

get {

return y;

}

}

public void Move(int dx, int dy) {

Show(false);

x += dx;

y += dy;

Show(true);

}

public void Show(bool visible) {

game. OnShowPlayer(this, visible);

}

}

public class Game {

protected ArrayList players = new ArrayList();

public event ShowPlayerHandler ShowPlayer;

public Player Connect() {

Player p = new Player(this);

players. Add(p);

OnShowPlayer(p, true);

return p;

}

public void Disconnect(Player p) {

OnShowPlayer(p, false);

players. Remove(p);

}

public void OnShowPlayer(Player p, bool visible) {

if(ShowPlayer != null)

ShowPlayer(p, visible);

}

}

}

Класс Game содержит массив всех игроков players и методы Connect и Disconnect для подсоединения и отключения игроков. Класс Player содержит координаты x и y игрока на плоскости и ссылку game на игру, к которой подключен игрок.

Обратите внимание на несколько нестандартную логику рисования. Метод Show класса Player не содержит кода для рисования игрока на экране, а просто вызывает метод OnShowPlayer объекта класса Game. Метод OnShowPlayer также не содержит кода для рисования игрока на экране, зато он генерирует событие ShowPlayer, обработчик которого будет произведено обновление экрана.

3. Добавление главного меню.

Добавим к приложению меню. Для этого перетащите из окна Toolbox на форму компонент MainMenu и добавим к нему пункт Game с подпунктами Start Server и Exit. Окно Toolbox может быть показано на экране при помощи пункта меню View\Toolbox или комбинации клавиш Ctrl + Alt + X. Чтобы в окне Toolbox появились компоненты пользовательского интерфейса, в окне редактора должен быть показано окно формы, а не ее исходный текст.

Откомпилируйте и запустите программу. У приложение появилось меню, но его пункты пока не работают.

4. Обработчик для пункта меню Exit.

Добавьте обработчик пункта меню Exit. Нажмите правую кнопку мыши в окне с редактором формы и в появившемся меню выберите пункт Properties.

В окне свойств пункта меню выберите список событий. Для этого нажмите кнопку с изображением молнии. В списке событий дважды нажмите левую кнопку мыши на событие Click.

Будет создан метод с именем menuItem3_Click, код которого сразу же отобразится в редакторе. Добавьте вызов метода Close() основной формы.

private void menuItem3_Click(object sender, System. EventArgs e) {

Close();

}

5. Подключение к серверу.

Создание игры и игрока будем выполнять в обработчике пункта меню Start Server. Добавьте к классу Form1 поля данных game и player для хранения ссылок на игру и локального игрока. Действуя аналогично пункту 4 создайте обработчик выбора пункта меню Start Server. Скорее всего, этот обработчик будет назваться menuItem2_Click.

public class Form1: System. Windows. Forms. Form {

protected Game game = null;

protected Player player = null;

private void menuItem2_Click(object sender, System. EventArgs e) {

game = new Game();

player = game. Connect();

}

}

Но даже после выполнения этих действий выбор пункта меню Start Server не приводит к изменению картинки на экране, т. к. еще на написан код для рисования игрока на экране.

6. Пиктограмма для отображения игрока.

Включите в файл приложения картинку для отображения игрока. Картинка находится в файле happy. bmp. В окне Solution Explorer нажмите правую кнопку мыши и в появившемся меню выберите пункт Add/Add Existing Item.. и в окне диалога укажите файл happy. bmp.

Для файла happy. bmp установите свойство Build Action равным “Embedded resource”. Теперь этот файл будет включен в файл приложения.

Создайте обработчик события Load. Для этого в окне свойств окна (формы) выберите список событий. Для этого нажмите кнопку с изображением молнии. В списке событий дважды нажмите левую кнопку мыши на событие Load.

Будет создан метод с именем Form1_Load, код которого сразу же отобразится в редакторе. Загрузку картинки удобно произвести в этом методе. Добавьте к классу Form1 поле playerPicture типа Bitmap и в методе Form1_Load присвойте ему ссылку на картинку из файла happy. bmp.

public class Form1: System. Windows. Forms. Form {

protected Bitmap playerPicture = null;

private void Form1_Load(object sender, System. EventArgs e) {

playerPicture = new Bitmap(typeof(Form1),"HAPPY. BMP");

}

...

}

7. Рисование игрока на экране.

Напишите обработчик события для отрисовки (или стирания) игрока на экране. Подсоедините обработчик к событию ShowPlayer объекта game. Код метода OnShowPlayer вы можене взять в файле scratch. cs под меткой 2.

...

public class Form1: System. Windows. Forms. Form {

….

private void menuItem2_Click(object sender, System. EventArgs e) {

game = new Game();

game. ShowPlayer += new ShowPlayerHandler(OnShowPlayer);

player = game. Connect();

}

public void OnShowPlayer(Player p, bool visible) {

using(Graphics g = CreateGraphics())

if(visible)

g. DrawImageUnscaled(playerPicture,

p. X - playerPicture. Width/2,

p. Y - playerPicture. Height/2);

else

using(Brush b = new SolidBrush(BackColor))

g. FillRectangle(b,

p. X - playerPicture. Width/2,

p. Y - playerPicture. Height/2,

playerPicture. Width,

playerPicture. Height);

}

}

Теперь после выбора пункта меню Start Server на экране появляется изображение игрока.

8. Передвижение игрока.

Добавьте к основной форме приложения обработчик события KeyDown (обработчик события KeyDown добавляется аналогично обработчику события Load). Разместите в этом обработчике код для передвижения игрока. Код можно взять в файле scratch. cs под меткой 3.

private void Form1_KeyDown(object sender,

System. Windows. Forms. KeyEventArgs e) {

if(player!= null) {

if(e. KeyCode == Keys. Left)

player. Move(-10,0);

else if(e. KeyCode == Keys. Right)

player. Move(10,0);

else if(e. KeyCode == Keys. Up)

player. Move(0,-10);

else if(e. KeyCode == Keys. Down)

player. Move(0,10);

}

}

Запустите программу. Игрок должен перемещаться при нажатии на клавиши со стрелками.

9. Обработка перерисовки окна.

Полученное приложение имеет следующий недостаток: если свернуть и развернуть окно или закрыть изображение игрока другим окном, то оно пропадает. Добавьте к форме обработчик события Paint. Добавьте в класс Game метод ShowAllPlayers для перерисовки всех игроков и вызовите его из обработчика события Paint. Чтобы окно перерисовывалось при изменении размера добавьте вызов метода SetStyle в обработчик события Load.

public class Form1 : System. Windows. Forms. Form {

private void Form1_Load(object sender, System. EventArgs e) {

playerPicture = new Bitmap(typeof(Form1),"HAPPY. BMP");

SetStyle(ControlStyles. ResizeRedraw, true);

}

private void Form1_Paint(object sender,

System. Windows. Forms. PaintEventArgs e) {

if(game!= null)

game. ShowAllPlayers();

}

}

public class Game {

/// <summary> Вызываем события перерисовки для всех игроков </summary>

public void ShowAllPlayers() {

foreach(Player p in players)

OnShowPlayer(p, true);

}

}

После выполнения этих действий изображение игрока не должно пропадать с экрана в любом случае.

10. Подключение библиотеки Runtime Remoting.

Теперь перейдем к самой интересной части: написании сетевого взаимодействия с применением технологии. NET Remoting. Добавьте к проекту ссылку на сборку *****ntime. Remoting. dll. Для этого в окне Solution Explorer нажмите правую кнопку мыши над элементом References и выберите в появившемся меню пункт Add Reference. В окне Add Reference добавьте в проект перечисленные сборку *****ntime. Remoting. dll при помощи кнопки Browse.

В самом начале исходного текста добавьте две директивы using. Это позволит обращаться к классам системы. NET Remoting не указывая каждый раз длинных префиксов пространств имен. Текст вы можете найти в файле scratch. cs под меткой 4.

using System;

using System. Drawing;

using System. Collections;

using ponentModel;

using System. Windows. Forms;

using System. Data;

// Используемые пространства имен

using *****ntime. Remoting;

using *****ntime. Remoting. Channels;

using *****ntime. Remoting. Channels. Tcp;

using *****ntime. Serialization. Formatters;

11. Создание канала для передачи сообщений.

Для передачи сообщений между программами требуется создать и зарегистрировать канал. Код для создания и настройки канала поместите в метод CreateChannel класса Form1. Код можно взять в файле Scratch. cs под меткой 5.

Сервер будет сообщать клиентам о перемещении игроков при помощи событий. Поэтому при создании канала необходимо явно указать возможность работы с типами-делегатами.

public class Form1 : System. Windows. Forms. Form {

...

TcpChannel CreateChannel(int port) {

BinaryServerFormatterSinkProvider sp = new

BinaryServerFormatterSinkProvider();

sp. TypeFilterLevel = TypeFilterLevel. Full; // Разрешаем передачу

// делегатов

BinaryClientFormatterSinkProvider cp = new

BinaryClientFormatterSinkProvider();

IDictionary props = new Hashtable();

props["port"] = port;

return new TcpChannel(props, cp, sp);

}

}

12. Запуск сервера.

Измените код обработчика пункта меню Start Server, который находится в методе menuItem2_Click класса Form1.

private void menuItem2_Click(object sender, System. EventArgs e) {

// Создаем канал, который будет слушать порт 8000

ChannelServices. RegisterChannel(CreateChannel(8000));

// Создаем объект-игру

game = new Game();

// Предоставляем объект-игру для вызова с других компьютеров

RemotingServices. Marshal(game,"GameObject");

// Входим в игру

game. ShowPlayer += new ShowPlayerHandler(OnShowPlayer);

player = game. Connect();

}

Чтобы объекты классов Game и Player могли быть доступны с других компьютеров, эти классы должны быть потомками класса MarshalByRefObject. Внесите соответствующие изменения в файл Form1.cs.

public class Player : MasrhalByRefObject {

}

public class Game : MarshalByRefObject {

}

Внешний вид окна не изменился, но наше приложение стало полноценным игровым сервером к которому возмножно подключиться с любого другого компьютера.

13. Подключение к серверу.

Добавьте в программу возможность подключения к серверу. Для этого к главному меню добавьте пункт Connect to Server (действуя аналогично пункту 4) в его обработчике (menuItem4_Click) напишите следующий код.

private void menuItem4_Click(object sender, System. EventArgs e) {

string serverName = "localhost"; // Тот же компьютер

// Создаем канал, который будет подключен к серверу

ChannelServices.RegisterChannel(CreateChannel(0));

// Получаем ссылку на объект-игру. расположенную на

// другом компьютере (или в другом процессе)

game = (Game)Activator. GetObject(typeof(Game),

String. Format("tcp://{0}:8000/GameObject",serverName));

// Входим в игру

game. ShowPlayer += new ShowPlayerHandler(OnShowPlayer);

player = game. Connect();

}

Запустите два (или больше) экземпляров приложения. В одном выберите пункт меню Start Server, в остальных – Connect. Перемещения всех игроков должны одновременно отображаться во всех окнах.

Программа работает следующим образом. Объекты класса Game и Player существуют только в программе-сервере. Все клиенты содержат только ссылки на эти объекты. Кроме того, каждый клиент содержит обработчик события ShowPlayer серверного объекта класса Game. При передвижении любого из игроков сервер генерирует событие ShowPlayer. Событие передается всем клиентам, которые в ответ на него отображают переместившегося игрока.

14. Исправление ошибок и недостатков.

В созданной программе достаточно много недоработок, некоторые из которых могут считаться ошибками J. Исправим большую часть из них.

При подключении к серверу другие игроки отображаются не сразу. Для исправления этого недостатка измените код метода Connect класса Game так, чтобы при подключении нового игрока вызывались события перерисовки для всех игроков.

...

public Player Connect() {

Player p = new Player(this);

players. Add(p);

ShowAllPlayers();

return p;

}

...

Запустите программу. Теперь при подключении к серверу в окне отображаются все игроки.

15. Продолжение исправления ошибок.

Если завершить одну из подсоединенных программ (неважно, будет это сервер или один из клиентов), то любое перемещение оставшихся игроков вызовет исключение. Корректно обработаем завершение программ. Это удобно сделать в обработчике события Closing формы Form1. Добавление обработчика события Closing происходит полностью аналогично обработчику события Load.

Клиентские программы будут уведомлять сервер о своем завершении, отменив регистрацию события ShowPlayer. Завершение сервера будет запрещено, пока подсоединен хотя бы один клиент. Для решения этой задачи потребуется свойство класса Game, возвращающее количество игроков в игре. Код обработчика Form1_Closing находится в файле scratch. cs под меткой 6.

...

public class Form1 : System. Windows. Forms. Form {

private void Form1_Closing(object sender,

ponentModel. CancelEventArgs e) {

if(game!= null) { // Подключены к игре

if(!RemotingServices. IsTransparentProxy(game)) // Мы на сервере

if(game. PlayerCount > 1) { // Кроме игрока на сервере

// другие есть клиенты

MessageBox. Show("You can\'t exit while “ +

“other players are connected");

e. Cancel = true; // Отменяем закрытие окна

return;

}

// Выходим из игры

game. Disconnect(player);

game. ShowPlayer -= new ShowPlayerHandler(OnShowPlayer); // Отменяем

// подписку на события

}

}

}

public class Game : MarshalByRefObject {

/// <summary> Количество игроков в игре </summary>

public int PlayerCount {

get {

return players. Count;

}

}

}

После выполнения этих действий при завершении клиента соответствующий игрок пропадает с экрана во всех программах (см. вызов события ShowPlayer в методе Disconnect класса Game), а завершение сервера невозможно, пока к нему подсоединен хотя бы один клиент.

16. И еще один недостаток...

Еще одним недостатком созданной программы является то, что после запуска сервера или подключения к серверу пункты меню Start Server и Connect остаются доступными. Повторный выбор этих пунктом меню приводит к возникновению исключения. Для решения этой проблемы измените обработчики событий menuItem2_Click и menuItem4_Click.

..

private void menuItem4_Click(object sender, System. EventArgs e) {

// Запрещаем повторное подключение или запуск сервера

menuItem2.Enabled = false;

menuItem4.Enabled = false;

}

private void menuItem2_Click(object sender, System. EventArgs e) {

// Запрещаем повторное подключение или запуск сервера

menuItem2.Enabled = false;

menuItem4.Enabled = false;

}

17. Форма для ввода строки.

Осталось добавить возможность подключения к серверам на других машинах. Создадим окно для ввода адреса сервера. Добавим в проект новую форму (назовите ее InputBox). Для этого нажмите правую кнопку мыши над именем проекта в окне Solution Explorer и выберите пункт меню Add\Add New Item…

В появившемся окне выберите пункт Windows Form и введите имя нового файла “InputBox. cs”

Из окна Toolbox перетащите на новую форму поле ввода (TextBox) и две кнопки (Button). Для кнопок установите значения свойств Text равными OK и Cancel, а значения свойств DialogResult равными DialogResult. OK и DialogResult. Cancel. Свойство Text строки ввода оставьте пустым.

Добавьте к коду InputBox свойство InputText для получения значения из текстового поля.

public class InputBox : System. Windows. Forms. Form {

public string InputText {

get {

return textBox1.Text;

}

}

}

18. Подключение к любому серверу.

В обработчике пункта меню Connect (он называется menuItem4_Click) получите имя сервера от пользователя при помощи созданной формы InputBox и присвойте его переменной serverName.

private void menuItem4_Click(object sender, System. EventArgs e) {

InputBox dlg = new InputBox();

if(dlg. ShowDialog() != DialogResult. OK)

return; // Отмена подключения

string serverName = dlg. InputText;

}

Теперь при подключении к серверу на экране появится окно, в котором можно ввести имя или IP-адрес сервера.

Для подключения к локальному компьютеру можно ввести имя localhost. Вы также можете скопировать свою программу на соседний компьютер и попробовать соединиться с сервером с другого компьютера. Имя компьютера можно узнать вызвав в командной строке утилиту ipconfig c ключом /all.

Источники литературы

Информатика. Основополагающее введение: В 4-х ч. Ч. 1./Пер. с нем. – М.: Диалог-МИФИ, 1996 – 300 с. Информатика. Вычислительные структуры и машинно-ориентированное программирование: В 4-х ч. Ч. 2./Пер. с нем. – М.: Диалог-МИФИ, 1998 – 224 с. Информатика. Структуры систем и системное программирование: В 4-х ч. Ч. 3./Пер. с нем. – М.: Диалог-МИФИ, 1996 – 224 с. Информатика. Теоретическая информатика, алгоритмы и структуры данных, логическое программирование, объектная ориентация: в 4-х ч. Ч. 4./Пер. с нем. – М.: Диалог-МИФИ, 1998 – 238с. Минипортал кафедры ТИССУ МИРЭА.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3