Beispiel #1
0
int main(int argc, const char *argv[])
{
	int ret;
	char ch;
	
	srand(time(NULL));
	ret = fb_open();
	key_init();	
	draw_back();
	draw_grid();
	signal(SIGALRM, sig_handler);
	alarm(1);

	while (1) {
		ch = getchar();
		switch (ch) {
			case 'a':
				if(canleft(pos_x, pos_y, cur_type, arr)) {
					draw_type(pos_x, pos_y, cur_type, BACK);
					pos_x--;
				}
				break;
			case 'd':
				if(canright(pos_x, pos_y, cur_type, arr)) {
					draw_type(pos_x, pos_y, cur_type, BACK);
					pos_x++;
				}
				break;	
			case 's':
				if(candown(pos_x, pos_y, cur_type, arr)) {
					draw_type(pos_x, pos_y, cur_type, BACK);
					pos_y++;
				}
				break;
			case 'w':
				if(canchange(pos_x,pos_y,cur_type,arr)) {
					draw_type(pos_x, pos_y, cur_type, BACK);
					type_chg(&cur_type);
				}
				break;
			default :
				break;
		}
		draw_type(pos_x, pos_y, cur_type, COLOR);
		draw_grid();
		if(!candown(pos_x, pos_y, cur_type, arr)) {
			draw_flag(pos_x, pos_y, cur_type, arr);
			if(gameover(arr)) {
				exit(0);
			}
			deleteone(arr);
			pos_x = XNUM/2; pos_y = 0;
			cur_type = rand()%14;
		}
	}

	fb_close();

	return 0;
}
Beispiel #2
0
void draw::draw_dog(){
    glPushMatrix();
        draw_back();
        draw_leg();
        //draw_tail();
        //draw_nnh();
    glPopMatrix();
}
Beispiel #3
0
void draw_card(struct card *card) {
  if (card->face == EXPOSED) {
    draw_front(card);
  } else {
    draw_back(card);
  }
  wrefresh(card->frame->window);
}
Beispiel #4
0
//==============================
// ゲームのメインの処理の関数 MAIN
// 呼ばれた後、毎回disp_frame()が呼ばれている。
//==============================
void game_main()
{



	// バーが動く

	// 自機をうごかす
	move_jiki();

	// 当たり判定
	
	// 画面クリア
	draw_back();
	// 自機を描く
	draw_jiki();
	//draw_line(5,5, 40,50, 0x00);
	//printf("end main().");
}
Beispiel #5
0
void screen_redraw()
{
  //d3dmgr->EndShapesBatching(); //If called inside bound surface we need to finish drawing
  d3dmgr->BeginScene();
  // Clean up any textures that ENIGMA may still think are binded but actually are not
  d3d_set_zwriteenable(true);
  if (!view_enabled)
  {
    screen_set_viewport(0, 0, window_get_region_width_scaled(), window_get_region_height_scaled());
    
    clear_view(0, 0, room_width, room_height, 0, background_showcolor);
    draw_back();
    draw_insts();
    draw_tiles();
  }
  else
  {
    //TODO: Possibly implement view option from Stupido to control which view clears the background
    // Only clear the background on the first visible view by checking if it hasn't been cleared yet
    bool draw_backs = true;
    bool background_allviews = true; // FIXME: Create a setting for this.
    for (view_current = 0; view_current < 8; view_current++)
    {
      int vc = (int)view_current;
      if (!view_visible[vc])
        continue;
      
      int vob = (int)view_object[vc];
      if (vob != -1)
        follow_object(vob, vc);

      screen_set_viewport(view_xport[vc], view_yport[vc], view_wport[vc], view_hport[vc]);
	  
      clear_view(view_xview[vc], view_yview[vc], view_wview[vc], view_hview[vc], view_angle[vc], background_showcolor && draw_backs);

      if (draw_backs)
        draw_back();
      
      draw_insts();
      
      if (draw_tiles())
        break;
      draw_backs = background_allviews;
    }
    view_current = 0;
  }

  // Now process the sub event of draw called draw gui
  // It is for drawing GUI elements without view scaling and transformation
  if (enigma::gui_used)
  {
    screen_set_viewport(0, 0, window_get_region_width_scaled(), window_get_region_height_scaled());
    d3d_set_projection_ortho(0, 0, enigma::gui_width, enigma::gui_height, 0);
	
    // Clear the depth buffer if hidden surface removal is on at the beginning of the draw step.
    if (enigma::d3dMode)
      d3dmgr->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    draw_gui();
  }

  d3dmgr->EndScene();

  ///TODO: screen_refresh() shouldn't be in screen_redraw(). They are separate functions for a reason.
  screen_refresh();
}
Beispiel #6
0
void screen_redraw()
{
	// Should implement extended lost device checking
	//if (d3ddev == NULL ) return;
	
	// Clean up any textures that ENIGMA may still think are binded but actually are not
	texture_reset();

    d3ddev->BeginScene();    // begins the 3D scene
	dsprite->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_DO_NOT_ADDREF_TEXTURE);
		
	if (!view_enabled)
    {
		D3DVIEWPORT9 pViewport = { 0, 0, (DWORD)window_get_region_width_scaled(), (DWORD)window_get_region_height_scaled(), 0, 1.0f };
		d3ddev->SetViewport(&pViewport);
		
		D3DXMATRIX matTrans, matScale;

		// Calculate a translation matrix
		D3DXMatrixTranslation(&matTrans, -0.5, -room_height - 0.5, 0);
		D3DXMatrixScaling(&matScale, 1, -1, 1);
		
		// Calculate our world matrix by multiplying the above (in the correct order)
		D3DXMATRIX matWorld = matTrans * matScale;

		// Set the matrix to be applied to anything we render from now on
		d3ddev->SetTransform( D3DTS_VIEW, &matWorld);
	
		D3DXMATRIX matProjection;    // the projection transform matrix
		D3DXMatrixOrthoOffCenterLH(&matProjection,
							0,
							(FLOAT)room_width,   
							0, 
							(FLOAT)room_height,   
							0.0f,    // the near view-plane
							1.0f);    // the far view-plane
		d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);    // set the projection transform
		
		if (background_showcolor)
		{
			int clearcolor = ((int)background_color) & 0x00FFFFFF;
			// clear the window to the background color
			d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(__GETR(clearcolor), __GETG(clearcolor), __GETB(clearcolor)), 1.0f, 0);
			// clear the depth buffer
		}

		// Clear the depth buffer if 3d mode is on at the beginning of the draw step.
        if (enigma::d3dMode)
			d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
		
        draw_back();

	
        // Apply and clear stored depth changes.
        for (map<int,pair<double,double> >::iterator it = id_to_currentnextdepth.begin(); it != id_to_currentnextdepth.end(); it++)
        {
            enigma::object_graphics* inst_depth = (enigma::object_graphics*)enigma::fetch_instance_by_id((*it).first);
            if (inst_depth != NULL) {
                drawing_depths[(*it).second.first].draw_events->unlink(inst_depth->depth.myiter);
                inst_iter* mynewiter = drawing_depths[(*it).second.second].draw_events->add_inst(inst_depth->depth.myiter->inst);
                if (instance_event_iterator == inst_depth->depth.myiter) {
                    instance_event_iterator = inst_depth->depth.myiter->prev;
                }
                inst_depth->depth.myiter = mynewiter;
            }
        }
        id_to_currentnextdepth.clear();

        if (enigma::particles_impl != NULL) {
            const double high = numeric_limits<double>::max();
            const double low = drawing_depths.rbegin() != drawing_depths.rend() ? drawing_depths.rbegin()->first : -numeric_limits<double>::max();
            (enigma::particles_impl->draw_particlesystems)(high, low);
        }
        bool stop_loop = false;
        for (enigma::diter dit = drawing_depths.rbegin(); dit != drawing_depths.rend(); dit++)
        {
            if (dit->second.tiles.size())
                //glCallList(drawing_depths[dit->second.tiles[0].depth].tilelist);

            texture_reset();
            enigma::inst_iter* push_it = enigma::instance_event_iterator;
            //loop instances
            for (enigma::instance_event_iterator = dit->second.draw_events->next; enigma::instance_event_iterator != NULL; enigma::instance_event_iterator = enigma::instance_event_iterator->next) {
                enigma::instance_event_iterator->inst->myevent_draw();
                if (enigma::room_switching_id != -1) {
                    stop_loop = true;
                    break;
                }
            }
            enigma::instance_event_iterator = push_it;
            if (stop_loop) break;
            //particles
            if (enigma::particles_impl != NULL) {
                const double high = dit->first;
                dit++;
                const double low = dit != drawing_depths.rend() ? dit->first : -numeric_limits<double>::max();
                dit--;
                (enigma::particles_impl->draw_particlesystems)(high, low);
            }
        }
		//return;
    }
    else
    {
        bool stop_loop = false;
        for (view_current = 0; view_current < 7; view_current++)
        {
            if (view_visible[(int)view_current])
            {
                int vc = (int)view_current;
                int vob = (int)view_object[vc];

                if (vob != -1)
                {
                    object_basic *instanceexists = fetch_instance_by_int(vob);

                    if (instanceexists)
                    {
                        object_planar* vobr = (object_planar*)instanceexists;

                        double vobx = vobr->x, voby = vobr->y;

                        //int bbl=*vobr.x+*vobr.bbox_left,bbr=*vobr.x+*vobr.bbox_right,bbt=*vobr.y+*vobr.bbox_top,bbb=*vobr.y+*vobr.bbox_bottom;
                        //if (bbl<view_xview[vc]+view_hbor[vc]) view_xview[vc]=bbl-view_hbor[vc];

                        double vbc_h, vbc_v;
                        (view_hborder[vc] > view_wview[vc]/2) ? vbc_h = view_wview[vc]/2 : vbc_h = view_hborder[vc];
                        (view_vborder[vc] > view_hview[vc]/2) ? vbc_v = view_hview[vc]/2 : vbc_v = view_vborder[vc];

                        if (view_hspeed[vc] == -1)
                        {
                            if (vobx < view_xview[vc] + vbc_h)
                                view_xview[vc] = vobx - vbc_h;
                            else if (vobx > view_xview[vc] + view_wview[vc] - vbc_h)
                                view_xview[vc] = vobx + vbc_h - view_wview[vc];
                        }
                        else
                        {
                            if (vobx < view_xview[vc] + vbc_h)
                            {
                                view_xview[vc] -= view_hspeed[vc];
                                if (view_xview[vc] < vobx - vbc_h)
                                    view_xview[vc] = vobx - vbc_h;
                            }
                            else if (vobx > view_xview[vc] + view_wview[vc] - vbc_h)
                            {
                                view_xview[vc] += view_hspeed[vc];
                                if (view_xview[vc] > vobx + vbc_h - view_wview[vc])
                                    view_xview[vc] = vobx + vbc_h - view_wview[vc];
                            }
                        }

                        if (view_vspeed[vc] == -1)
                        {
                            if (voby < view_yview[vc] + vbc_v)
                                view_yview[vc] = voby - vbc_v;
                            else if (voby > view_yview[vc] + view_hview[vc] - vbc_v)
                                view_yview[vc] = voby + vbc_v - view_hview[vc];
                        }
                        else
                        {
                            if (voby < view_yview[vc] + vbc_v)
                            {
                                view_yview[vc] -= view_vspeed[vc];
                                if (view_yview[vc] < voby - vbc_v)
                                    view_yview[vc] = voby - vbc_v;
                            }
                            if (voby > view_yview[vc] + view_hview[vc] - vbc_v)
                            {
                                view_yview[vc] += view_vspeed[vc];
                                if (view_yview[vc] > voby + vbc_v - view_hview[vc])
                                    view_yview[vc] = voby + vbc_v - view_hview[vc];
                            }
                        }

                        if (view_xview[vc] < 0)
                            view_xview[vc] = 0;
                        else if (view_xview[vc] > room_width - view_wview[vc])
                            view_xview[vc] = room_width - view_wview[vc];

                        if (view_yview[vc] < 0)
                            view_yview[vc] = 0;
                        else if (view_yview[vc] > room_height - view_hview[vc])
                            view_yview[vc] = room_height - view_hview[vc];
                    }
                }
				
				D3DVIEWPORT9 pViewport = { (DWORD)view_xport[vc], (DWORD)view_yport[vc], 
					(DWORD)(window_get_region_width_scaled() - view_xport[vc]), (DWORD)(window_get_region_height_scaled() - view_yport[vc]), 0, 1.0f };
				d3ddev->SetViewport(&pViewport);
		
				D3DXMATRIX matTrans, matScale;

				// Calculate a translation matrix
				D3DXMatrixTranslation(&matTrans, -view_xview[vc] - 0.5, -view_yview[vc] - room_height - 0.5, 0);
				D3DXMatrixScaling(&matScale, 1, -1, 1);
		
				// Calculate our world matrix by multiplying the above (in the correct order)
				D3DXMATRIX matWorld = matTrans * matScale;

				// Set the matrix to be applied to anything we render from now on
				d3ddev->SetTransform( D3DTS_VIEW, &matWorld);
	
				D3DXMATRIX matProjection;    // the projection transform matrix
				D3DXMatrixOrthoOffCenterLH(&matProjection,
							0,
							(FLOAT)view_wview[vc],   
							0, 
							(FLOAT)view_hview[vc],   
							0.0f,    // the near view-plane
							1.0f);    // the far view-plane
				d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);    // set the projection transform
				
				if (background_showcolor && view_current == 0)
				{
					int clearcolor = ((int)background_color) & 0x00FFFFFF;
					// clear the window to the background color
					d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(__GETR(clearcolor), __GETG(clearcolor), __GETB(clearcolor)), 1.0f, 0);
				}
				
				// Clear the depth buffer if 3d mode is on at the beginning of the draw step.
                if (enigma::d3dMode)
                    d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

                if (view_current == 0) {
					draw_back();
				}

                // Apply and clear stored depth changes.
                for (map<int,pair<double,double> >::iterator it = id_to_currentnextdepth.begin(); it != id_to_currentnextdepth.end(); it++)
                {
                    enigma::object_graphics* inst_depth = (enigma::object_graphics*)enigma::fetch_instance_by_id((*it).first);
                    if (inst_depth != NULL) {
                        drawing_depths[(*it).second.first].draw_events->unlink(inst_depth->depth.myiter);
                        inst_iter* mynewiter = drawing_depths[(*it).second.second].draw_events->add_inst(inst_depth->depth.myiter->inst);
                        if (instance_event_iterator == inst_depth->depth.myiter) {
                            instance_event_iterator = inst_depth->depth.myiter->prev;
                        }
                        inst_depth->depth.myiter = mynewiter;
                    }
                }
                id_to_currentnextdepth.clear();

                if (enigma::particles_impl != NULL) {
                    const double high = numeric_limits<double>::max();
                    const double low = drawing_depths.rbegin() != drawing_depths.rend() ? drawing_depths.rbegin()->first : -numeric_limits<double>::max();
                    (enigma::particles_impl->draw_particlesystems)(high, low);
                }
                for (enigma::diter dit = drawing_depths.rbegin(); dit != drawing_depths.rend(); dit++)
                {
                    if (dit->second.tiles.size())
                        //glCallList(drawing_depths[dit->second.tiles[0].depth].tilelist);

                    texture_reset();
                    enigma::inst_iter* push_it = enigma::instance_event_iterator;
                    //loop instances
                    for (enigma::instance_event_iterator = dit->second.draw_events->next; enigma::instance_event_iterator != NULL; enigma::instance_event_iterator = enigma::instance_event_iterator->next) {
                        enigma::instance_event_iterator->inst->myevent_draw();
                        if (enigma::room_switching_id != -1) {
                            stop_loop = true;
                            break;
                        }
                    }
                    enigma::instance_event_iterator = push_it;
                    if (stop_loop) break;
                    //particles
                    if (enigma::particles_impl != NULL) {
                        const double high = dit->first;
                        dit++;
                        const double low = dit != drawing_depths.rend() ? dit->first : -numeric_limits<double>::max();
                        dit--;
                        (enigma::particles_impl->draw_particlesystems)(high, low);
                    }
                }
                if (stop_loop) break;
            }
        }
        view_current = 0;
    }
	
	int culling = d3d_get_culling();
	d3d_set_culling(rs_none);

	// Now process the sub event of draw called draw gui
	// It is for drawing GUI elements without view scaling and transformation
    if (enigma::gui_used)
    {
		// Now process the sub event of draw called draw gui 
		// It is for drawing GUI elements without view scaling and transformation
		D3DVIEWPORT9 pViewport = { 0, 0, window_get_region_width_scaled(), window_get_region_height_scaled(), 0, 1.0f };
		d3ddev->SetViewport(&pViewport);
		
		D3DXMATRIX matTrans, matScale;

		// Calculate a translation matrix
		D3DXMatrixTranslation(&matTrans, -0.5, -room_height - 0.5, 0);
		D3DXMatrixScaling(&matScale, 1, -1, 1);
		
		// Calculate our world matrix by multiplying the above (in the correct order)
		D3DXMATRIX matWorld = matTrans * matScale;

		// Set the matrix to be applied to anything we render from now on
		d3ddev->SetTransform( D3DTS_VIEW, &matWorld);
	
		D3DXMATRIX matProjection;    // the projection transform matrix
		D3DXMatrixOrthoOffCenterLH(&matProjection,
							0,
							(FLOAT)enigma::gui_width,   
							0, 
							(FLOAT)enigma::gui_height,   
							0.0f,    // the near view-plane
							1.0f);    // the far view-plane
		d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);    // set the projection transform

		//dsprite->SetWorldViewRH(NULL, &matWorld);

		// Clear the depth buffer if hidden surface removal is on at the beginning of the draw step.
        if (enigma::d3dMode)
			d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
			
		d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
			
        bool stop_loop = false;
        for (enigma::diter dit = drawing_depths.rbegin(); dit != drawing_depths.rend(); dit++)
        {
            enigma::inst_iter* push_it = enigma::instance_event_iterator;
            //loop instances
            for (enigma::instance_event_iterator = dit->second.draw_events->next; enigma::instance_event_iterator != NULL; enigma::instance_event_iterator = enigma::instance_event_iterator->next) {
				enigma::instance_event_iterator->inst->myevent_drawgui();
                if (enigma::room_switching_id != -1) {
                    stop_loop = true;
                    break;
                }
            }
            enigma::instance_event_iterator = push_it;
            if (stop_loop) break;
        }
		
	}
	
	// Textures should be clamped when rendering 2D sprites and stuff, so memorize it.
	DWORD wrapu, wrapv, wrapw;
	d3ddev->GetSamplerState( 0, D3DSAMP_ADDRESSU, &wrapu );
	d3ddev->GetSamplerState( 0, D3DSAMP_ADDRESSV, &wrapv );
	d3ddev->GetSamplerState( 0, D3DSAMP_ADDRESSW, &wrapw );
	
	d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
	d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
	d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP );
	// The D3D sprite batcher uses clockwise face culling which is default but can't tell if 
	// this here should memorize it and force it to CW all the time and then reset what the user had
	// or not.
	//d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
	dsprite->End();
	// And now reset the texture repetition.
	d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSU, wrapu );
	d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSV, wrapv );
	d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSW, wrapw );
	
	// reset the culling
	d3d_set_culling(culling);
    d3ddev->EndScene();    // ends the 3D scene
		
	screen_refresh();
}
Beispiel #7
0
void screen_redraw()
{
  // Clean up any textures that ENIGMA may still think are binded but actually are not
  d3d_set_zwriteenable(true);
  if (!view_enabled)
  {
    if (bound_framebuffer != 0) //This fixes off-by-one error when rendering on surfaces. This should be checked to see if other GPU's have the same effect
      screen_set_viewport(1, 1, window_get_region_width_scaled(), window_get_region_height_scaled());
    else
      screen_set_viewport(0, 0, window_get_region_width_scaled(), window_get_region_height_scaled());
    
    clear_view(0, 0, room_width, room_height, background_showcolor);
    draw_back();
    draw_insts();
    draw_tiles();
  }
  else
  {
    //TODO: Possibly implement view option from Stupido to control which view clears the background
    // Only clear the background on the first visible view by checking if it hasn't been cleared yet
    bool draw_backs = true;
    bool background_allviews = true; // FIXME: Create a setting for this.
    for (view_current = 0; view_current < 8; view_current++)
    {
      int vc = (int)view_current;
      if (!view_visible[vc])
        continue;
      
      int vob = (int)view_object[vc];
      if (vob != -1)
        follow_object(vob, vc);

      if (bound_framebuffer != 0) //This fixes off-by-one error when rendering on surfaces. This should be checked to see if other GPU's have the same effect
        screen_set_viewport(view_xport[vc]+1, view_yport[vc]+1, view_wport[vc], view_hport[vc]);
      else
        printf("%d %d %d %d\n", (int)view_xport[vc], (int)view_yport[vc], (int)view_wport[vc], (int)view_hport[vc]),
        screen_set_viewport(view_xport[vc], view_yport[vc], view_wport[vc], view_hport[vc]);
	  
      clear_view(view_xview[vc], view_yview[vc], view_wview[vc], view_hview[vc], background_showcolor && draw_backs);

      if (draw_backs)
        draw_back();
      
      draw_insts();
      
      if (draw_tiles())
        break;
      draw_backs = background_allviews;
    }
    view_current = 0;
  }

  // Now process the sub event of draw called draw gui
  // It is for drawing GUI elements without view scaling and transformation
  if (enigma::gui_used)
  {
    screen_set_viewport(0, 0, window_get_region_width_scaled(), window_get_region_height_scaled());
	d3d_set_projection_ortho(0, 0, enigma::gui_width, enigma::gui_height, 0);
	
    // Clear the depth buffer if hidden surface removal is on at the beginning of the draw step.
    if (enigma::d3dMode)
      glClear(GL_DEPTH_BUFFER_BIT);

    draw_gui();
  }

  if (enigma::msaa_fbo != 0) {
    GLint fbo;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, enigma::msaa_fbo);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    //TODO: Change the code below to fix this to size properly to views
    glBlitFramebuffer(0, 0, window_get_region_width_scaled(), window_get_region_height_scaled(), 0, 0, window_get_region_width_scaled(), window_get_region_height_scaled(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    // glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
  }

  ///TODO: screen_refresh() shouldn't be in screen_redraw(). They are separate functions for a reason.
  if (bound_framebuffer==0 || enigma::msaa_fbo != 0) { screen_refresh(); }
}
Beispiel #8
0
void game_init(int ai)
{
	static int once = 1;
	int x, y;
	BITMAP *tmp;
	int bc = makecol(200, 150, 50);
	
	clear_to_color(screen, makecol(0, 0, 0));
	textout_centre(screen, font, "Generating&Caching Data", SCREEN_W / 2, 0, -1);
	textout_centre(screen, font, "May take a while", SCREEN_W / 2, SCREEN_H / 2, -1);
	textout_centre(screen, font, "(about 10 minutes for first run,", SCREEN_W / 2, SCREEN_H / 2 + 20, -1);
	textout_centre(screen, font, "about 1 minute every first game,", SCREEN_W / 2, SCREEN_H / 2 + 40, -1);
	textout_centre(screen, font, "few seconds else)", SCREEN_W / 2, SCREEN_H / 2 + 60, -1);
		
	if (once) {
		once = 0;
		
		animdata[0] = load_gfx("gravburn", 48);
		animdata[1] = load_gfx("shock", 48);
		animdata[2] = load_gfx("fireball", 48);
		animdata[3] = load_gfx("wheel", 48);
		animdata[4] = load_gfx("glow", 32);
		{
			int a;
			for (a = 0; a < ANIMS; a++) {
				anim[a] = 0;
				animlen[a] = dat_length(animdata[a]);
			}
		}
		
		tower = dat[TOWER_BMP].dat;
		explosion = dat[EXPLOSION_WAV].dat;
		radiating =  dat[RADIATING_WAV].dat;
		teleport =  dat[TELEPORT_WAV].dat;
		bonus =  dat[BONUS_WAV].dat;
		nuclearegg =  dat[NUCLEAREGG_BMP].dat;
		launcher =  dat[LAUNCHER_BMP].dat;
	
		bonuspic[0] = dat[BONUS0_BMP].dat;
		bonuspic[1] = dat[BONUS1_BMP].dat;
		bonuspic[2] = dat[BONUS2_BMP].dat;
	
		map = create_bitmap(SCREEN_W, SCREEN_H);
	}

	ignore[0] = 0;
	ignore[1] = 0;	
	think[0] = 0;
	think[1] = 0;
	memorized[0] = 0;
	memorized[1] = 0;
	AI[0] = 0;
	if (ai) AI[1] = 1; else AI[1] = 0;
	power[0] = 0;
	power[1] = 0;
	bonusnum = 0;
	life[0] = 100;
	life[1] = 100;
	go = 0;
	
	turn = 0;
	
	tmp = create_bitmap_ex(32, SCREEN_W, SCREEN_H);
	draw_back(tmp);
	for (y = 0; y < 16; y++) {
		for (x = 0; x < 16; x++) {
			hills[y][x] = rnd();
		}
	}

	basex[0] = 4 * TW + TW / 2;
	basey[0] = 4 * TH + TH / 2;

	basex[1] = 12 * TW + TW / 2;
	basey[1] = 12 * TH + TH / 2;

	hills[4][4] = 1;
	hills[5][4] = 1;
	hills[5][5] = 1;
	hills[4][5] = 1;

	hills[12][12] = 1;
	hills[13][12] = 1;
	hills[13][13] = 1;
	hills[12][13] = 1;

	x = rnd() * 16;
	y = rnd() * 16;

	for (y = 0; y < MH; y++) {
		for (x = 0; x < MW; x++) {
			int c = 0;
			int t;
			float height = get_height(x, y);
			float h = 0, z = height * ZZZ;
			for (h = height, t = 0; z > 0 && t < 2; z--, h -= 1.0 / (float)ZZZ, t++) {
				int r, g, b;
				float l;
				if (h < 0.2) {
					float p = h / 0.2;
					r = 0;
					g = 100 * p;
					b = 155 + 100 * p;
				} else if (h < 0.5) {
					float p = (h - 0.2) / 0.3;
					r = 0;
					g = 100 + 155 * p;
					b = 255 - 155 * p;
				} else if (h < 0.8) {
					float p = (h - 0.5) / 0.3;
					r = 200 * p;
					g = 255 - 155 * p;
					b = 100;
				} else {
					float p = (h - 0.8) / 0.2;
					r = 200;
					g = 100 + 100 * p;
					b = 100 + 100 * p;
				}
				l = get_height(x + 1, y) - get_height(x, y + 1);
				r = r + l * 2000 + (rnd() - 0.5) * 20;
				g = g + l * 2000 + (rnd() - 0.5) * 20;
				b = b + l * 2000 + (rnd() - 0.5) * 20;
				c = makecol32(M(r), M(g), M(b));
				if (y == MH - 1 && h < height) c = bc;
				putpixel(tmp, 88 + x, y + WINT - z, c);
			}
		}
	}
	{
		float filter[3][3] = {
			{0.025, 0.145, 0.025},
			{0.145, 0.320, 0.145},
			{0.025, 0.145, 0.025}
		};
		for (y = 0; y < SCREEN_H; y++) {
			for (x = 0; x < SCREEN_W; x++) {
				int i = 0, j = 0;
				float r = 0, g = 0, b = 0;
				for (i = -1; i <= 1; i++) {
					for (j = -1; j <= 1; j++) {
						int c = getpixel(tmp, x + j, y + i);
						if (c < 0) c = makecol32(0, 0, 0);
						r += getr32(c) * filter[1 + i][1 + j];
						g += getg32(c) * filter[1 + i][1 + j];
						b += getb32(c) * filter[1 + i][1 + j];
					}
				}
				putpixel(map, x, y, makecol(r, g, b));
			}
		}
	}
	destroy_bitmap(tmp);
	ballx = 240;
	bally = 240;
	balldx = 0;
	balldy = 0;
}