Click here to Skip to main content
15,897,968 members
Articles / Desktop Programming / MFC

2D LUA Based Robot Simulator

Rate me:
Please Sign up or sign in to vote.
4.89/5 (26 votes)
14 Apr 2014Public Domain9 min read 131.2K   7.9K   119  
An article on designing your own robot simulator
��// AzollaView.cpp : implementation of the CAzollaView class

//





#include "stdafx.h"

#include "Azolla.h"



#include "AzollaDoc.h"

#include "AzollaView.h"



#include <vector>



#ifdef _DEBUG

#define new DEBUG_NEW

#endif



// CAzollaView



IMPLEMENT_DYNCREATE(CAzollaView, CView)



BEGIN_MESSAGE_MAP(CAzollaView, CView)

	// Standard mouse events

	ON_WM_MOUSEMOVE()

	ON_WM_LBUTTONUP()

	ON_WM_LBUTTONDOWN()

	// Screen

	ON_WM_ERASEBKGND()

	//UI update

	ON_UPDATE_COMMAND_UI(ID_SIMULATION_RUN, OnUpdateRunButton)

	ON_UPDATE_COMMAND_UI(ID_SIMULATION_STOP, UnUpdateStopButton)

	ON_UPDATE_COMMAND_UI(ID_ROBOT_SHOWTRAIL, OnUpdateDrawTrail)

	ON_UPDATE_COMMAND_UI(ID_WORLD_SHOWGRID, OnUpdateShowGrid)

	// General

	ON_COMMAND(ID_VIEW_ROBOTPROPERTIES, CAzollaView::OnViewProperty)

	ON_COMMAND(ID_VIEW_EDITOR, CAzollaView::OnViewEditor)

	ON_COMMAND(ID_ROBOT_SETPROPERTIES, CAzollaView::OnViewSetProperty)

	ON_COMMAND(ID_SIMULATION_RUN, CAzollaView::OnRun)

	ON_COMMAND(ID_SIMULATION_STOP, CAzollaView::OnStop)

	ON_COMMAND(ID_ROBOT_RESETPOSITION, CAzollaView::OnResetRobot)

	ON_COMMAND(ID_WORLD_CLEARWORLD, CAzollaView::OnClearWorld)

	ON_COMMAND(ID_ROBOT_SHOWTRAIL, CAzollaView::OnDrawTrail)

	ON_COMMAND(ID_WORLD_SHOWGRID, CAzollaView::OnShowGrid)

	// Buttin for drawing objects

	ON_COMMAND(ID_BTRECT, CAzollaView::OnBtRect)

	ON_COMMAND(ID_BTCIRC, CAzollaView::OnBtCirc)

	ON_COMMAND(ID_BTLINE, CAzollaView::OnBtLine)

	ON_COMMAND(ID_BTDEL, CAzollaView::OnBtDel)

	ON_COMMAND(ID_BTSELECTALL, CAzollaView::OnBtSelectAll)

END_MESSAGE_MAP()



// CAzollaView construction/destruction

CAzollaView::CAzollaView()

{

	// Init robot

	m_propertyDlg = NULL;

	m_editorDlg = NULL;

	m_evaluate = NULL;

	m_bManuallyMoved = false;

	m_bRunning = false;

	m_isShowGrid = true;



	// Prepare dynamic variables

	m_timeStep = new float;

	m_evaluate = new CEvaluate;

}



CAzollaView::~CAzollaView()

{

	// Destroy window & clean up memory

	// Clean m_propertyDlg

	if (m_propertyDlg)

    {

		if (::IsWindow(m_propertyDlg->GetSafeHwnd()))

            m_propertyDlg->EndDialog(IDCANCEL);

		m_propertyDlg->DestroyWindow();

		delete m_propertyDlg;

    }



	// Clean m_editorDlg

	if (m_editorDlg){

        if (::IsWindow(m_editorDlg->GetSafeHwnd()))

            m_editorDlg->EndDialog(IDCANCEL);

		m_editorDlg->DestroyWindow();

		delete m_editorDlg;

    }



	if (m_evaluate)

		delete m_evaluate;



	delete m_timeStep;

}



BOOL CAzollaView::PreCreateWindow(CREATESTRUCT& cs)

{

	m_canvas.setSnapToGrid(true, 10, 10);

	return CView::PreCreateWindow(cs);

}



// CAzollaView drawing

void CAzollaView::OnDraw(CDC* dc)

{

	CMemDC pDC(dc);



	CAzollaDoc* pDoc = GetDocument();

	pDoc->m_canvas = &m_canvas;

	ASSERT_VALID(pDoc);



	if (m_isShowGrid)

		m_canvas.drawGrid(&pDC, this->GetSafeHwnd(), 50, 50);

	m_canvas.update(&pDC);

	m_robot.DrawRobot(&pDC);



	m_canvas.setMessage(m_evaluate->getMsg());

}



BOOL CAzollaView::OnEraseBkgnd(CDC* pDC) 

{

	return FALSE;

}



// CAzollaView diagnostics

#ifdef _DEBUG

void CAzollaView::AssertValid() const

{

	CView::AssertValid();

}



void CAzollaView::Dump(CDumpContext& dc) const

{

	CView::Dump(dc);

}



CAzollaDoc* CAzollaView::GetDocument() const // non-debug version is inline

{

	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAzollaDoc)));

	return (CAzollaDoc*)m_pDocument;

}

#endif //_DEBUG





// CAzollaView message handlers

/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////



void CAzollaView::OnMouseMove(UINT nFlags, CPoint point)

{

	CView::OnMouseMove(nFlags, point);



	// Update end point while mouse is moving

	if (GetCapture() == this){

		m_ptEnd = point;

		Invalidate();

		m_canvas.set(m_ptStart, m_ptEnd);

	}



	// Drag robot manually

	if (m_bManuallyMoved){

		m_ptEnd = point;

		m_robot.SetPosition(m_ptEnd);



		// Update robot property values on proerty dialog box

		if (m_propertyDlg)

			m_propertyDlg->update();



		Invalidate();

	}

}



void CAzollaView::OnLButtonDown(UINT nFlags, CPoint point)

{

	CView::OnLButtonDown(nFlags, point);



	// Get start point for drawing

	m_ptStart = m_ptEnd = point;

	

	// Drag robot manually BUT don't move if simulation is running

	if (m_robot.IsRobotDetected(m_ptEnd) && !m_bRunning){

		m_bManuallyMoved = true;

		m_robot.SetPosition(m_ptEnd);

		Invalidate();

	}



	// For canvas

	else{

		SetCapture();

		m_canvas.set(m_ptStart, m_ptEnd);

	}

}



void CAzollaView::OnLButtonUp(UINT nFlags, CPoint point)

{

	CView::OnLButtonUp(nFlags, point);



	// Get end point for drawing

	if (GetCapture() == this)

	{ 

		ReleaseCapture();

		m_ptEnd = point;

		Invalidate();

		m_canvas.store();

	}



	if (!m_bRunning){

		// Drag robot manually, skip if simulation is running

		m_bManuallyMoved = false;

		m_robot.UpdateInitialPos();

	}

}



DWORD WINAPI CAzollaView::simulationThread(LPVOID param)

{

	CAzollaView *obj = (CAzollaView *)param;

	obj->simulationThreadWorker();

	return 0;

}



void CAzollaView::simulationThreadWorker()

{

	m_robot.InitNoiseGenerator();



	while(m_bRunning && !m_evaluate->isItDone()){

		m_robot.GoRobotGo(m_timeStep);



		Invalidate(FALSE);



		// Update robot property values on proerty dialog box

		if (m_propertyDlg)

			m_propertyDlg->update();



		// Hold up, manipulate this to set simulaton speed!

		//    We can not do invalidation too fast, minimum 10 ms (100Hz)

		Sleep(17); //60Hz

	}



	m_bRunning = false;

	Invalidate();

}



void CAzollaView::OnRun()

{

	// Load code from editor to buffer then run it

	if(m_editorDlg && m_bRunning == false){

		// Retrieve code

		CString codes;

		m_editorDlg->GetText(codes);



		// Handle empty scripts

		if (codes.IsEmpty()){

			return;

		}



		// Prepare to run

		int ret = m_evaluate->init(codes, &m_robot);



		if (ret == 0){ // No error

			// Init and start a new thread for simulation

			*m_timeStep = 0;

			m_bRunning = true;



			DWORD thid;

			CreateThread(NULL, 0, simulationThread, this, 0, &thid);

		}

		else

			m_canvas.setMessage( m_evaluate->getMsg());

	}



	else

		m_canvas.setMessage("Open the editor with CTRL + E\n");



	Invalidate();

}



void CAzollaView::OnStop()

{

	if(m_bRunning){

		m_evaluate->setQuitFlag();

		m_bRunning = false;

		m_robot.UpdateInitialPos(); // We need to update initial position after simulation stops

	}

}



void CAzollaView::OnViewProperty()

{

	if (!m_propertyDlg)

		m_propertyDlg = new CPropertyDlg;



	m_propertyDlg->m_robot = &m_robot;



	if (!::IsWindow(m_propertyDlg->GetSafeHwnd()))

		m_propertyDlg->Create(IDD_SHOWPROPERTIES);



	m_propertyDlg->ShowWindow(SW_SHOW);

}



void CAzollaView::OnViewEditor()

{

	if (!m_editorDlg)

		m_editorDlg = new CEditorDlg;



	if (!::IsWindow(m_editorDlg->GetSafeHwnd()))

		m_editorDlg->Create(IDD_EDITOR, GetDesktopWindow());



	m_editorDlg->ShowWindow(SW_SHOW);

	m_editorDlg->SetActiveWindow();

}



void CAzollaView::OnViewSetProperty()

{

	CSetPropertyDlg setPropertyDlg;

	setPropertyDlg.m_robot = &m_robot;

	setPropertyDlg.DoModal();

	Invalidate();

}





void CAzollaView::OnBtCirc()

{

	m_canvas.set(TOOL_CIRCLE);

}



void CAzollaView::OnBtRect()

{

	m_canvas.set(TOOL_RECTANGLE);

}



void CAzollaView::OnBtLine()

{

	m_canvas.set(TOOL_LINE);

}



void CAzollaView::OnBtDel()

{

	m_canvas.set(TOOL_DELETE);

}



void CAzollaView::OnBtSelectAll()

{

	m_canvas.selectAll();

	Invalidate();

}



void CAzollaView::OnResetRobot()

{

	// Stop simulation if running

	OnStop();

	// Init robot with default values. 

	// TODO: read from configuration file!

	m_robot.SetPosition(CPoint(100,100));

	m_robot.SetAngle(0);

	m_robot.UpdateInitialPos();

	m_robot.mPos0 = CPoint(100,100);

	

	// Refresh screen

	Invalidate();

}



void CAzollaView::OnDrawTrail()

{

	m_robot.SetDrawTrailStatus(!m_robot.GetDrawTrailStatus());

}



void CAzollaView::OnShowGrid()

{

	m_isShowGrid = !m_isShowGrid;

	Invalidate();

}



void CAzollaView::OnClearWorld()

{

	m_canvas.clearAll();

	Invalidate();

}



void CAzollaView::OnUpdateRunButton(CCmdUI* pCmdUI)

{

	pCmdUI->Enable(!m_bRunning);

}



void CAzollaView::UnUpdateStopButton(CCmdUI* pCmdUI)

{

	pCmdUI->Enable(m_bRunning);

}



void CAzollaView::OnUpdateDrawTrail(CCmdUI* pCmdUI)

{

	pCmdUI->SetCheck((int) m_robot.GetDrawTrailStatus());

}



void CAzollaView::OnUpdateShowGrid(CCmdUI* pCmdUI)

{

	pCmdUI->SetCheck((int) m_isShowGrid);

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Student
Indonesia Indonesia
http://kataauralius.com/

Comments and Discussions