📄 cubes.cpp.in
字号:
/**************************************************************************\ * * This file is part of a set of example programs for the Coin library. * Copyright (C) 2000-2003 by Systems in Motion. All rights reserved. * * <URL:http://www.coin3d.org> * * This sourcecode can be redistributed and/or modified under the * terms of the GNU General Public License version 2 as published by * the Free Software Foundation. See the file COPYING at the root * directory of the distribution for more details. * * As a special exception, all sourcecode of the demo examples can be * used for any purpose for licensees of the Coin Professional * Edition License, without the restrictions of the GNU GPL. See our * web pages for information about how to acquire a Professional Edition * License. * * Systems in Motion, <URL:http://www.sim.no>, <mailto:support@sim.no> *\**************************************************************************//* ********************************************************************** * * Cubes * * A C++/Coin rewrite of the famous game CUBES originally written by * the same author in MC68000 assembly for Commodore Amiga computers * in 1990/91. * * Author: Marius Kintel (kintel@sim.no) * ********************************************************************** *//* TODO *================= * * - Tune draggers; constraints ? * X Keyboard-mode: Full game play * - Drag & drop balls * - Textured board/balls? * - Add manipulator-camera * - Ball line-up * - Ball animation (bounce) * X 4-on-a-row animation (blink?, fireworks?) * - Instructions: Ghost balls?, Coin-logo, text * - AI * o Deepen search on forced moved * o Randomization * o Computer vs. Computer * - Undo winning move */#if HAVE_CONFIG_H#include <config.h>#endif // HAVE_CONFIG_H#include <Inventor/@Gui@/So@Gui@.h>#include <Inventor/@Gui@/viewers/So@Gui@ExaminerViewer.h>#include <Inventor/events/SoKeyboardEvent.h>#include <Inventor/events/SoLocation2Event.h>#include <Inventor/events/SoMouseButtonEvent.h>#include <Inventor/nodes/SoAntiSquish.h>#include <Inventor/nodes/SoCube.h>#include <Inventor/nodes/SoCone.h>#include <Inventor/nodes/SoCylinder.h>#include <Inventor/nodes/SoCoordinate3.h>#include <Inventor/nodes/SoFaceSet.h>#include <Inventor/nodes/SoEventCallback.h>#include <Inventor/nodes/SoCallback.h>#include <Inventor/nodes/SoMaterial.h>#include <Inventor/nodes/SoOrthographicCamera.h>#include <Inventor/nodes/SoPerspectiveCamera.h>#include <Inventor/nodes/SoDirectionalLight.h>#include <Inventor/nodes/SoRotor.h>#include <Inventor/nodes/SoTransform.h>#include <Inventor/nodes/SoScale.h>#include <Inventor/nodes/SoSeparator.h>#include <Inventor/nodes/SoSwitch.h>#include <Inventor/nodes/SoShapeHints.h>#include <Inventor/nodes/SoSphere.h>#include <Inventor/nodes/SoSurroundScale.h>#include <Inventor/nodes/SoText2.h>#include <Inventor/nodes/SoText3.h>#include <Inventor/nodes/SoTexture2.h>#include <Inventor/nodes/SoTextureCoordinate2.h>#include <Inventor/nodes/SoTextureCoordinateBinding.h>#include <Inventor/nodes/SoTextureCoordinateEnvironment.h>#include <Inventor/nodes/SoTranslation.h>#include <Inventor/nodes/SoSelection.h>#include <Inventor/nodes/SoLight.h>#include <Inventor/fields/SoMFInt32.h>#include <Inventor/sensors/SoTimerSensor.h>#include <Inventor/elements/SoViewportRegionElement.h>#include <Inventor/engines/SoCompose.h>#include <Inventor/engines/SoSelectOne.h>#include <Inventor/engines/SoTimeCounter.h>#include <Inventor/engines/SoOnOff.h>#include <Inventor/draggers/SoTranslate1Dragger.h>#include <Inventor/draggers/SoTranslate2Dragger.h>#include <Inventor/manips/SoTransformerManip.h>#include <Inventor/actions/SoSearchAction.h>#include <Inventor/actions/SoRayPickAction.h>#include <Inventor/actions/SoWriteAction.h>#include <Inventor/SoPickedPoint.h>#include <coin-competitions/coinlogo.h>#include <coin-competitions/TextureWriter.h>#include "GameLogic.h"#include <math.h>#include <stdio.h>#include <stdlib.h> // exit()#include <time.h>#include <assert.h>So@Gui@RenderArea *viewer;// So@Gui@ExaminerViewer *viewer;SoSwitch *tokenmat;SoSwitch *tokensw;SoTranslation *tokenTrans;SoSwitch *redswitches[4*4*4];SoSwitch *blueswitches[4*4*4];SoSelectOne *selectone;SoTimeCounter *timecounter;SoPath *isectpath;SoFaceSet *isectfaceset;SoSwitch *sceneswitch;TextureWriter out(80,26);GameLogic *game;bool mouseInside=false;// Enables the "hovering" tokenvoid enable_token(Token color){ if (color==NONE) { tokensw->whichChild.setValue(SO_SWITCH_NONE); } else if (color==RED) { tokensw->whichChild.setValue(SO_SWITCH_ALL); tokenmat->whichChild.setValue(0); } else if (color==BLUE) { tokensw->whichChild.setValue(SO_SWITCH_ALL); tokenmat->whichChild.setValue(1); } else assert(false);}void move_token(int x, int y){ SbVec3f currPos = tokenTrans->translation.getValue(); currPos[0] = x*2-3; currPos[2] = -y*2+3; tokenTrans->translation.setValue(currPos);}void move_token(){ int x,y; game->getCurrPos(x,y); move_token(x,y);}void place_token(int x, int y, int z, Token color){ int idx = x+4*y+16*z; if (color==RED) redswitches[idx]->whichChild.setValue(SO_SWITCH_ALL); else if (color==BLUE) blueswitches[idx]->whichChild.setValue(SO_SWITCH_ALL); else assert(false);}void remove_token(int x, int y, int z, Token color){ int idx = x+4*y+16*z; if (color==RED) redswitches[idx]->whichChild.setValue(SO_SWITCH_NONE); else if (color==BLUE) blueswitches[idx]->whichChild.setValue(SO_SWITCH_NONE); else assert(false);}void clear_board(){ for (int i=0;i<4*4*4;i++) { redswitches[i]->whichChild.setValue(SO_SWITCH_NONE); blueswitches[i]->whichChild.setValue(SO_SWITCH_NONE); } timecounter->on.setValue(false);}void add_token(){ int x,y,z; Token col; if (game->getLastPos(x,y,z,col)) { place_token(x,y,z,col); bool winner = game->validate(); if (winner) {// printf("WINNER: %s\n",col==RED?"Red":"Blue"); enable_token(NONE); int idx[4]; game->getSolution(idx[0],idx[1],idx[2],idx[3]); if (col==RED) { redswitches[idx[0]]->whichChild.connectFrom(selectone->output); redswitches[idx[1]]->whichChild.connectFrom(selectone->output); redswitches[idx[2]]->whichChild.connectFrom(selectone->output); redswitches[idx[3]]->whichChild.connectFrom(selectone->output); } else { blueswitches[idx[0]]->whichChild.connectFrom(selectone->output); blueswitches[idx[1]]->whichChild.connectFrom(selectone->output); blueswitches[idx[2]]->whichChild.connectFrom(selectone->output); blueswitches[idx[3]]->whichChild.connectFrom(selectone->output); } timecounter->on.setValue(true); } else { if (game->onePlayer() && game->isComputersTurn()) { game->getSuggestedMove(x,y); game->moveTo(x,y); if (game->add()) { add_token(); } } else { enable_token(game->getWhoseTurn()); } } } else assert(false);}voidmove_token(SbVec2s screenpos){ SoRayPickAction pick(viewer->getViewportRegion()); pick.setPoint(screenpos); pick.apply(isectpath); SoPickedPoint *pp = pick.getPickedPoint(); if (pp) { mouseInside=true; const SoPath *path = pp->getPath(); int l=path->getLength(); SbVec3f op = pp->getObjectPoint(); if (game->isInGame()) { int x,y; if (op[0]<-2) x=0; else if (op[0]<0) x=1; else if (op[0]<2) x=2; else x=3; if (op[2]<-2) y=3; else if (op[2]<0) y=2; else if (op[2]<2) y=1; else y=0; if (game->moveTo(x,y)) move_token(); } } else mouseInside=false;} voidbutton_event_cb(void *userdata, SoEventCallback *node){ const SoMouseButtonEvent *event = (SoMouseButtonEvent *)node->getEvent(); if (game->isInGame()) { SbVec2s pos = event->getPosition(viewer->getViewportRegion()); move_token(pos); // To make sure it is updated even if user doesn't // move the mouse. if (mouseInside && event->getButton()==SoMouseButtonEvent::BUTTON1 && event->getState()==SoButtonEvent::UP) { if (game->add()) { add_token(); } } }}voidmouse_event_cb(void *userdata, SoEventCallback *node){ const SoEvent *event = node->getEvent(); if (game->isInGame()) { SbVec2s pos = event->getPosition(viewer->getViewportRegion()); move_token(pos); }}voidevent_cb(void *userdata, SoEventCallback *node){ const SoEvent *event = node->getEvent(); if (SO_KEY_PRESS_EVENT(event, ENTER)) { if (game->add()) { add_token(); } } else if (SO_KEY_PRESS_EVENT(event, LEFT_ARROW)) { if (game->move(-1,0)) { move_token(); } } else if (SO_KEY_PRESS_EVENT(event, RIGHT_ARROW)) { if (game->move(1,0)) { move_token(); } } else if (SO_KEY_PRESS_EVENT(event, UP_ARROW)) { if (game->move(0,1)) { move_token(); } } else if (SO_KEY_PRESS_EVENT(event, DOWN_ARROW)) { if (game->move(0,-1)) { move_token(); } } else if (SO_KEY_PRESS_EVENT(event, BACKSPACE)) { if (game->isInGame()) { Token col; int x,y,z; if (game->undo(col,x,y,z)) { remove_token(x,y,z,col); } if (game->onePlayer()) { if (game->undo(col,x,y,z)) { remove_token(x,y,z,col); } } } } else if (SO_KEY_PRESS_EVENT(event, NUMBER_1)) { if (game->start(RED, true)) { clear_board(); enable_token(game->getWhoseTurn()); move_token(0,0); } } else if (SO_KEY_PRESS_EVENT(event, NUMBER_2)) { if (game->start(RED, false)) { clear_board(); enable_token(game->getWhoseTurn()); move_token(0,0); } } else if (SO_KEY_PRESS_EVENT(event, H)) { sceneswitch->whichChild.setValue(1); } else if (SO_KEY_PRESS_EVENT(event, Q)) { exit(1); }}voidhelp_key_cb(void *userdata, SoEventCallback *node){ const SoEvent *event = node->getEvent(); if (!SO_KEY_RELEASE_EVENT(event, H)) { sceneswitch->whichChild.setValue(0); }}void setViewportCB(void *data, SoAction *action){ if (action->isOfType(SoGLRenderAction::getClassTypeId())) { SbViewportRegion curVP, newVP; curVP = ((SoGLRenderAction*)action)->getViewportRegion(); newVP = curVP; newVP.setViewport( 0.0, 0.0, 0.1, 0.1); SoState *state = action->getState(); SoViewportRegionElement::set( state, newVP ); }}SoSeparator *create_board(SoEngineOutput *rotxfield,SoEngineOutput *rotyfield){ SoSeparator *board = new SoSeparator; // Rotations SoRotation *rot = new SoRotation; rot->rotation.connectFrom(rotyfield); board->addChild(rot); rot = new SoRotation; rot->rotation.connectFrom(rotxfield); board->addChild(rot); SoSeparator *bsep = new SoSeparator; board->addChild(bsep); // Bottom plate SoMaterial *mat = new SoMaterial; mat->diffuseColor.setValue(0.44,0.20,0.11); mat->specularColor.setValue(0.71,0.33,0.18); bsep->addChild(mat); SoCube *plate = new SoCube; plate->height.setValue(0.5); plate->width.setValue(10); plate->depth.setValue(10); bsep->addChild(plate); // Intersection plane SoSeparator *intersep = new SoSeparator; bsep->addChild(intersep); SoMaterial *imat = new SoMaterial; imat->transparency.setValue(1); intersep->addChild(imat); SoTranslation *itrans = new SoTranslation; itrans->translation.setValue(0,4.375,0); intersep->addChild(itrans); SoCoordinate3 *coord = new SoCoordinate3; coord->point.set1Value(0,-5,0,-5); coord->point.set1Value(1,5,0,-5); coord->point.set1Value(2,5,0,5); coord->point.set1Value(3,-5,0,5); intersep->addChild(coord); isectfaceset = new SoFaceSet; isectfaceset->numVertices.setValue(4); intersep->addChild(isectfaceset); // Add cylinders SoSeparator *cylsep = new SoSeparator; bsep->addChild(cylsep); mat = new SoMaterial; mat->specularColor.setValue(1.0f, 0.0f, 0.0f); mat->emissiveColor.setValue(0.5f, 0.3f, 0.0f); mat->shininess = 0.8f; cylsep->addChild(mat); SoCylinder *cyl = new SoCylinder; cyl->radius.setValue(0.05); cyl->height.setValue(4.25); SbVec3f move; move.setValue(-3,2.25,-3); for (int j=0;j<4;j++) { for (int i=0;i<4;i++) { SoTranslation *trans = new SoTranslation; trans->translation.setValue(move); cylsep->addChild(trans); cylsep->addChild(cyl); move.setValue(2,0,0); } move.setValue(-6,0,2); } SoSeparator *tokensep = new SoSeparator; tokenTrans = new SoTranslation; tokenmat = new SoSwitch; tokensw = new SoSwitch; SoSphere *token = new SoSphere; SoMaterial *redmat = new SoMaterial; SoMaterial *bluemat = new SoMaterial; board->addChild(tokensep); tokensep->addChild(tokenTrans); tokensep->addChild(tokenmat); tokensep->addChild(tokensw); tokenmat->addChild(redmat); tokenmat->addChild(bluemat); tokensw->addChild(token); token->radius.setValue(0.5); tokensw->whichChild.setValue(SO_SWITCH_NONE); tokenmat->whichChild.setValue(SO_SWITCH_NONE); redmat->diffuseColor.setValue(1.0, 0.0, 0.0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -