Старые игрушки к старому Новому году -8



image

Среди ретро-софта есть отдельный вид, называемый игрушки (toys) в отличие от игр (games). Две игрушки, которые сегодня нашел в своем старом архиве, когда-то во времена MS DOS вызывали бурный восторг, может, и сейчас кого-то повеселят :)

А начинающим будет нескучно решить несколько занимательных задач.

У меня менее древняя реализация для Windows (вплоть до XP SP3) на Delphi-7. Источники, к сожалению, не помню.

Первая игрушка называется Noga. Запускаем exe-файл и видим, как по десктопу идет кто-то невидимый, оставляя следы:

image

Вторая игрушка Flip – просто переворачивает десктоп:

image

Устройство очень простое. На стандартую форму помещаем стандартные таймер и список картинок (TimageList). Список содержит картинки ног:

imageimage
(в программах использован bmp-формат, но в habrastorage.org он недопустим)

Интервал таймера выставляем 1000 мсек., свойство Enabled в True. Исходный код почти тривиальный (задача №1 начинающему – самостоятельно разобраться, как он работает).

noga код
unit noga;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, ImgList;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Image1: TImage;
    ImageList1: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Image1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    curX,curY,dx, dy : integer;
    lBitmap,rBitmap : tbitmap;
    procedure prepMainWindow;
    procedure drawNogas;
  end;

var
  Form1: TForm1;

implementation
 uses Clipbrd;
{$R *.DFM}

procedure TForm1.prepMainWindow;
var
        h,hMem : HDC;
        w,cl : HWnd;
        xSz,ySz : integer;
        bitmap : TBitmap{HBITMAP};
        bt : HBITMAP;
begin
// decktop capture
  hide;
  w := HWND_DESKTOP;
  h := GetDeviceContext(w);
  xSz :=  GetDeviceCaps(h,HORZRES);
  ySz :=  GetDeviceCaps(h,VERTRES);
  hMem := CreateCompatibleDC (h);

  bitmap := TBitmap.Create;
  bitmap.width := xSz;
  bitmap.height := ySz;
  bt := CreateCompatibleBitmap (h,xSz,ySz);
  SelectObject (hMem,bt{bitmap.Handle});
  StretchBlt (hMem, 0,0, xSz,ySz,
                h, 0,0, xSz,ySz, SRCCOPY);
  show;
  width := xSz;
  height := ySz;
  bitmap.Handle := bt;
  bitmap.HandleType := bmDIB; {(bmDIB, bmDDB)}
  Image1.Picture.Graphic := Bitmap;
  Bitmap.free;
// Left Noga
  lBitmap := TBitmap.Create;
  ImageList1.GetBitmap(0,lBitmap);
  lBitmap.transparent := true;
// Right Noga
  rBitmap := TBitmap.Create;
  ImageList1.GetBitmap(1,rBitmap);
  rBitmap.transparent := true;
// --------------------
  dx := xSz div 2;
  dy := ySz div 20;
  curX := dx;
  curY := ySz -dy;
end;

procedure TForm1.drawNogas;
begin
  messageBeep (mb_Ok);
  Canvas.draw(curX-lBitmap.width,curY,lBitmap);
  curY := curY -2*dy{-lBitmap.height};
  Canvas.draw(curX{+lBitmap.width},curY,rBitmap);
  curY := curY -4*dy;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 prepMainWindow;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
    if curY > 0
     then
       drawNogas
     else
       Timer1.Enabled := false;
end;

procedure TForm1.Image1Click(Sender: TObject);
begin
         Application.Terminate;
end;

end.


Вторая игрушка легко получается из первой:

flip код
unit noga;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure Image1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    curX,curY,dx, dy : integer;
    lBitmap,rBitmap : tbitmap;
    procedure test;
  end;

var
  Form1: TForm1;

implementation
 uses Clipbrd;
{$R *.DFM}

procedure TForm1.test;
var
        h,hMem : HDC;
        w,cl : HWnd;
        xSz,ySz,x,y : integer;
        bitmap,bitmap2 : TBitmap{HBITMAP};
        bt : HBITMAP;
begin
        hide;
        screen.cursor := crHourGlass;
  w := HWND_DESKTOP;
  h := GetDeviceContext(w);
  xSz :=  GetDeviceCaps(h,HORZRES);
  ySz :=  GetDeviceCaps(h,VERTRES);
  hMem := CreateCompatibleDC (h);

  bitmap := TBitmap.Create;
  bitmap.width := xSz;
  bitmap.height := ySz;
  bt := CreateCompatibleBitmap (h,xSz,ySz);
  SelectObject (hMem,bt{bitmap.Handle});
  StretchBlt (hMem, 0,0, xSz,ySz,
                h, 0,0, xSz,ySz, SRCCOPY);
  width := xSz;
  height := ySz;
 bitmap.Handle := bt;
 bitmap.HandleType := bmDIB; 
bitmap2 := TBitmap.Create;
  bitmap2.width := xSz;
  bitmap2.height := ySz;
  for y:=1 to ySz do
        for x :=1 to xSz do
                bitmap2.Canvas.Pixels [x,y]:=
                bitmap.Canvas.Pixels [xSz-x+1,ySz-y+1];

Image1.Picture.Graphic := Bitmap2;
  show;
  screen.cursor := crDefault;
  Bitmap.free;
  Bitmap2.free;

end;


procedure TForm1.FormCreate(Sender: TObject);
begin
 test;
end;

procedure TForm1.Image1Click(Sender: TObject);
begin
         Application.Terminate;
end;

end.


В заключение еще задачки для начинающих.

Задача №2. С последующими ОС (например, Windows 8.1) приведенный код работать не будет. Нужно переделать. Почитать (Гугл в помощь) и подумать о совместимости ОС Windows.

Примечание. Кто хочет попробовать данные игрушки, но не хочет ставить на диск такую «устаревшую» ОС, как Windows XP, — может поставить ее на виртуальную машину.

Задача №3 (можно объединить с предыдущей). ООП Паскаль Delphi-7 всё еще относительно популярен, но сейчас многие предпочитают другие языки. Переведите код на свой любимый язык под любимую IDE.

Примечание. Стиль кода может быть улучшен. Это можно сделать при переводе.

Задача №4. Объедините приведенные программы в одну, т.е. следы должны появляться на перевернутом десктопе.

Задача №5. Если Вы знакомы с программированием под Linux и/или MacOS – попробуйте портировать.

Задача №6. Попробуйте придумать другие забавные игрушки (toys).

Желаю веселого старого Нового года!

Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (16):

  1. TonyLorencio
    /#19603156 / +2

    Переведите код на свой любимый язык под любимую IDE.

    Все-таки в идеальном случае код вообще не должен быть привязан к IDE.

    • third112
      /#19603190 / -3

      Согласен, что в некоторых случаях м.б. принципиально, чтобы код был не привязан к IDE. В других это не имеет значение. Но для начинающего м.б. проще работать с компонентами (таймер, форма, список картинок и т.д.)

      (BTW Я и не говорю: привязать код к IDE. Работать можно под разными IDE (если они есть) в одном проекте, сохраняя независимость от них кода).

    • third112
      /#19603746

      TonyLorencio доказательство предъявите?:

      в идеальном случае код вообще не должен быть привязан к IDE


      А то уж больно нелепо звучит в одной фразе.

  2. maxzh83
    /#19603286

    В школе делал что-то подобное (но я бы не назвал это «игрушкой»), программа делала снимок экрана, потом разворачивалась на весь экран поверх всех окон, отображая сделанный снимок. Создавалось впечатление, что компьютер завис.

    • third112
      /#19603326 / -1

      ИМХО если есть практическая цель, нпр., сделать снимок экрана, чтобы сохранить его в файл, то это не игрушка, а инструмент. А если цель посмеяться над испуганным товарищем, то игрушка :)

  3. bvn13
    /#19603360 / +1

    А как же «глаза», «пингвин», «снежки» и «котик»?

    • third112
      /#19603436 / -1

      Глаза видел, другие не помню. Где посмотреть? Они старые?

  4. lleo_aha
    /#19603362 / +4

    Задача №7: Давайте удалим этот полезный и информативный пост

  5. vesper-bot
    /#19603386

    На некоторых системах Flip неплохо реализуется шорткатом Ctrl+Alt+Down Arrow. Да ещё и остается интерактивным. Чем не игрушка? :)

    • TonyLorencio
      /#19603442

      Это утилита видеодрайвера, насколько я помню.

  6. OlegIn_Geolog
    /#19603456

    У нас в моде была довольно жестокая шутка (не игрушка, хотя можно было и написать простенький код, но проще было руками сделать). Вместо стандартной заставки Screensaver ставилась знаменитая картинка с надписью «Теперь питание компьютера можно отключить». Человек уходил на перекур, чай, кофе, возвращался, видел экран, сильно удивлялся, еще сильнее расстраивался по поводу несохраненных данных, но питание выключал.

    • yar3333
      /#19603538

      Из аналогичного — сделать скрин экрана и поставить его картинкой на рабочий стол. После чего спрятать или удалить иконки с рабочего стола :)

  7. Ableness
    /#19603570

    Ноги — скукота, а вот овечки были весьма прелестны lurkmore.to/Screenmates

    • third112
      /#19603714

      Но! Они в GUI, а я про MS DOS. В Офисе и пресловутого Помощника можно рассматривать, как овечку.

  8. stavinsky
    /#19603618

    На старых мониках вообще можно было яркость выкрутить.
    А еще есть вот такой сайт. В фул скрине люди пугаются fakeupdate.net
    А в целом не понятно к чему этот информационный пост.

    • third112
      /#19603658

      А в целом не понятно к чему этот информационный пост.

      К Новому году, Карл :)